I'm trying to convert a date string into an age.
The string is like: "Mon, 17 Nov 2008 01:45:32 +0200" and I need to work out how many days old it is.
I have sucessfully converted the date using:
>>> time.strptime("Mon, 17 Nov 2008 01:45:32 +0200","%a, %d %b %Y %H:%M:%S +0200")
(2008, 11, 17, 1, 45, 32, 0, 322, -1)
For some reason %z gives me an error for the +0200 but it doesn't matter that much.
I can get the current time using:
>>> time.localtime()
(2009, 2, 3, 19, 55, 32, 1, 34, 0)
but how can I subtract one from the other without going though each item in the list and doing it manually?
You need to use the module datetime and the object datetime.timedelta
from datetime import datetime
t1 = datetime.strptime("Mon, 17 Nov 2008 01:45:32 +0200","%a, %d %b %Y %H:%M:%S +0200")
t2 = datetime.now()
tdelta = t2 - t1 # actually a datetime.timedelta object
print tdelta.days
In Python, datetime objects natively support subtraction:
from datetime import datetime
age = datetime.now() - datetime.strptime(...)
print age.days
The result is a timedelta object.
from datetime import datetime, timedelta
datetime.now()
datetime.datetime(2009, 2, 3, 15, 17, 35, 156000)
datetime.now() - datetime(1984, 6, 29 )
datetime.timedelta(8985, 55091, 206000)
datetime.now() - datetime(1984, 6, 29 )
datetime.timedelta(8985, 55094, 198000) # my age...
timedelta(days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])
If you don't want to use datetime (e.g. if your Python is old and you don't have the module), you can just use the time module.
s = "Mon, 17 Nov 2008 01:45:32 +0200"
import time
import email.utils # Using email.utils means we can handle the timezone.
t = email.utils.parsedate_tz(s) # Gets the time.mktime 9-tuple, plus tz
d = time.time() - time.mktime(t[:9]) + t[9] # Gives the difference in seconds.
Thanks guys, I ended up with the following:
def getAge( d ):
""" Calculate age from date """
delta = datetime.now() - datetime.strptime(d, "%a, %d %b %Y %H:%M:%S +0200")
return delta.days + delta.seconds / 86400.0 # divide secs into days
Giving:
>>> getAge("Mon, 17 Nov 2008 01:45:32 +0200")
78.801319444444445
Since Python 3.2, datetime.strptime() returns an aware datetime object if %z directive is provided:
#!/usr/bin/env python3
from datetime import datetime, timezone, timedelta
s = "Mon, 17 Nov 2008 01:45:32 +0200"
birthday = datetime.strptime(s, '%a, %d %b %Y %H:%M:%S %z')
age = (datetime.now(timezone.utc) - birthday) / timedelta(1) # age in days
print("%.0f" % age)
On older Python versions the correct version of #Tony Meyer's answer could be used:
#!/usr/bin/env python
import time
from email.utils import parsedate_tz, mktime_tz
s = "Mon, 17 Nov 2008 01:45:32 +0200"
ts = mktime_tz(parsedate_tz(s)) # seconds since Epoch
age = (time.time() - ts) / 86400 # age in days
print("%.0f" % age)
Both code examples produce the same result.
Related
I get the following error in which you can see the time data and the format I am using
time data '20:07:35 EEDT Wed Mar 31 2021' does not match format '%H:%M:%S %Z %a %b %d %Y'
I used the directives from here and I see that the format matches the description of each directive.
Can you see what is the issue here?
import datetime
time = '20:07:35 EEDT Wed Mar 31 2021'
time = time.replace('EEDT', '+0300')
datetime.datetime.strptime(time, '%H:%M:%S %z %a %b %d %Y')
you can map the abbreviated time zone to a IANA time zone name by dateutil's parser:
import dateutil
s = '20:07:35 EEDT Wed Mar 31 2021'
tzmapping = {"EEDT": dateutil.tz.gettz('Europe/Athens'),
"EEST": dateutil.tz.gettz('Europe/Athens')} # add more if needed...
dtobj = dateutil.parser.parse(s, tzinfos=tzmapping)
that will give you
dtobj
# >>> datetime.datetime(2021, 3, 31, 20, 7, 35, tzinfo=tzfile('Europe/Athens'))
dtobj.utcoffset()
# >>> datetime.timedelta(seconds=10800) # UTC+3
Note that timedelta arithmetic works correctly, i.e. includes DST changes:
from datetime import timedelta
dtobj -= timedelta(7) # DST change: dtobj is now EEST, UTC+2
dtobj.utcoffset()
# >>> datetime.timedelta(seconds=7200)
Problem is with EEDT. If you ignore EEDT(quickfix, not ideal), then your code may look like:
text = '20:07:35 EEDT Wed Mar 31 2021';
fmt = '%H:%M:%S EEDT %a %b %d %Y';
datetime.strptime(text, fmt)
--edit--
parsing datetime with timezone is difficult to pure datetime module. I'm not big expert, but pytz or python-datetutil should be good choice, according to this page: https://medium.com/#nqbao/python-timezone-and-daylight-savings-e511a0093d0
For those who are interested in different approach for similar, like GMT and BST or EEST and EEDT, it can be represented like this:
import datetime
try:
Time1 = datetime.datetime.strptime(DropTm,"%a %b %d %H:%M:%S GMT %Y")
except:
Time1 = datetime.datetime.strptime(DropTm,"%a %b %d %H:%M:%S BST %Y")
In your situation it will be:
import datetime
try:
Time1 = datetime.datetime.strptime(SomeValue,"%H:%M:%S EEDT %a %b %d %Y")
except:
Time1 = datetime.datetime.strptime(SomeValue,"%H:%M:%S EEST %a %b %d %Y")
Where is "SomeValue" your data!!
It did worked for me and do not need any other libraries! Good Luck with coding!!!
I'm trying to make a simple system which would get the current time and get another time after few secs, then see the difference with both of the times, so it's 2 seconds. So what I need is the other format like this > YEAR,MONTH,DAY HOUR:MIN.
This is the code which I use for this purpose, but in brackets there are just an example of the format I need.
a = datetime.datetime.now( %Y, %m %d %H:%M)
time.sleep(2)
b = datetime.datetime.now( %Y, %m %d %H:%M)
print(b-a)
print(a)
print(b)
I thing strftime is what you're looking for
import datetime
import time
a = datetime.datetime.now()
time.sleep(2)
b = datetime.datetime.now()
print(b-a)
print(a.strftime("%Y, %m, %d %H:%M"))
print(b.strftime("%Y, %m, %d %H:%M"))
prints
0:00:02.001719
2019, 09, 04 15:17
2019, 09, 04 15:17
For more formats, you can see strftime reference: https://www.programiz.com/python-programming/datetime/strftime.
You can convert a datetime.datetime instance to a string formatted to your liking using the strftime() function. For instance, to print with your preferred formatting you could do the following:
>>> import datetime
>>> a = datetime.datetime.now()
>>> print(a.strftime("%Y, %m %d %H:%M")
2019, 09 04 17:11
Subtracting two dates will yield a datetime.timedelta object, you can convert this to the number of seconds using the total_seconds() function:
>>> import datetime
>>> from time import sleep
>>> a = datetime.datetime.now()
>>> sleep(2)
>>> b = datetime.datetime.now()
>>> delta = b - a
>>> print(delta.total_seconds())
2.001301
I'd like to convert this time Sat, 19 May 2018 16:32:56 +0000 to 20180519-113256 in a local timezone (EDT in this example) in python. Could anybody show me how to do it?
PS., The following example shows how to convert time to local timezone. But I am not sure how to parse Sat, 19 May 2018 16:32:56 +0000.
Convert UTC datetime string to local datetime with Python
You could choose any timezone you want:
import pytz
from datetime import datetime
s = 'Sat, 19 May 2018 16:32:56 +0000'
dt = datetime.strptime(s, '%a, %d %b %Y %H:%M:%S %z')
tz = pytz.timezone('America/Chicago')
new_s = dt.astimezone(tz).strftime('%Y%m%d-%H%M%S')
for me this works:
from datetime import datetime
from dateutil import tz
def convert(date, from_zone = 'UTC', to_zone='America/New_York'):
from_zone = tz.gettz(from_zone)
to_zone = tz.gettz(to_zone)
date = date.replace(tzinfo=from_zone)
central = date.astimezone(to_zone)
return date
s = "Sat, 19 May 2018 16:32:56 +0000"
d = datetime.strptime(s, '%a, %d %B %Y %H:%M:%S +%f')
d = convert(d)
I have a timestamp that represents milliseconds since 1970 1432202088224 which translates to Thursday, May 21, 2015 5:54:48 AM EDT. I'd like to write a python function that converts that timestamp to milliseconds in GMT. I can't naively add four hours (3600000 milliseconds) to the existing timestamp because half the year i'll be off by one hour.
I've tried writing a function using datetime and pytz
def convert_mills_GMT(milliseconds):
converted_raw = datetime.datetime.fromtimestamp(milliseconds/1000.0)
date_eastern = eastern.localize(converted_raw, is_dst=True)
date_utc = date_eastern.astimezone(utc)
return int(date_utc.strftime("%s")) * 1000
using the input of 1432202088224 this function returns 1432220088000 which is Thursday, May 21, 2015 10:54:48 AM EDT when what I want is 9:54 AM. what am I missing?
There is no such thing as "EST timestamp". If you need "GMT timestamp" then you already have it.
To get UTC time from a POSIX timestamp given as number of milliseconds:
>>> from datetime import datetime, timedelta
>>> timestamp = 1432202088224
>>> utc_time = datetime(1970, 1, 1) + timedelta(milliseconds=timestamp)
>>> utc_time.strftime('%A, %B %d, %Y %H:%M:%S %p UTC')
'Thursday, May 21, 2015 09:54:48 AM UTC'
We can check that the result is correct by converting the UTC time back to "EST" timezone:
>>> import pytz # $ pip install pytz
>>> est = utc_time.replace(tzinfo=pytz.utc).astimezone(pytz.timezone('US/Eastern'))
>>> est.strftime('%A, %B %d, %Y %H:%M:%S %p %Z')
'Thursday, May 21, 2015 05:54:48 AM EDT'
Don't use .strftime("%s"). It is not supported, and may silently fail. Instead, to convert a UTC datetime to a timestamp use one of the methods shown here depending on your version of Python:
Python 3.3+:
timestamp = dt.timestamp()
Python3 (< 3.3):
epoch = datetime(1970, 1, 1, tzinfo=timezone.utc)
timestamp = (dt - epoch) / timedelta(seconds=1)
Python 2.7+:
timestamp = (dt.replace(tzinfo=None) - datetime(1970, 1, 1)).total_seconds()
Python2 (< 2.7):
def totimestamp(dt, epoch=datetime(1970,1,1)):
td = dt - epoch
# return td.total_seconds()
return (td.microseconds + (td.seconds + td.days * 86400) * 10**6) / 10**6
timestamp = totimestamp(dt.replace(tzinfo=None))
Therefore, your convert_mills_GMT should look like
def convert_mills_GMT(milliseconds,
utc=pytz.utc,
eastern=pytz.timezone('US/Eastern')
):
converted_raw = DT.datetime.fromtimestamp(milliseconds/1000.0)
date_eastern = eastern.localize(converted_raw, is_dst=True)
date_utc = date_eastern.astimezone(utc)
timestamp = ...
return int(timestamp) * 1000
For example, with Python2.7,
import datetime as DT
import pytz
def convert_mills_GMT(milliseconds,
utc=pytz.utc,
eastern=pytz.timezone('US/Eastern')
):
converted_raw = DT.datetime.fromtimestamp(milliseconds/1000.0)
date_eastern = eastern.localize(converted_raw, is_dst=True)
date_utc = date_eastern.astimezone(utc)
timestamp = ((date_utc.replace(tzinfo=None) - DT.datetime(1970, 1, 1))
.total_seconds())
return int(timestamp) * 1000
print(DT.datetime.utcfromtimestamp(convert_mills_GMT(1432202088224)/1000.0))
prints
2015-05-21 09:54:48
I have dates in the current string format: 'Tue Feb 19 00:09:28 +1100 2013'
I'm trying to figure out how many days have passed between the date in the string and the present date.
I've been able to convert the string into a date.
import time
day = time.strptime('Tue Feb 19 00:09:28 +1100 2013', '%a %b %d %H:%M:%S +1100 %Y')
Use the datetime module instead:
import datetime
day = datetime.datetime.strptime('Tue Feb 19 00:09:28 +1100 2013', '%a %b %d %H:%M:%S +1100 %Y')
delta = day - datetime.datetime.now()
print delta.days
Subtracting two datetime.datetime values returns a datetime.timedelta object, which has a days attribute.
Your strings do contain a timezone offset, and you hardcoded it to match; if the value varies you'll have to use a parser that can handle the offset. The python-dateutil package includes both an excellent parser and the timezone support to handle this:
>>> from dateutil import parser
>>> parser.parse('Tue Feb 19 00:09:28 +1100 2013')
datetime.datetime(2013, 2, 19, 0, 9, 28, tzinfo=tzoffset(None, 39600))
Note that because this result includes the timezone, you now need to use timezone-aware datetime objects when using date arithmetic:
>>> from dateutil import tz
>>> import datetime
>>> utcnow = datetime.datetime.now(tz.tzutc())
>>> then = parser.parse('Tue Feb 19 00:09:28 +1100 2013')
>>> utcnow - then
datetime.timedelta(31, 12087, 617740)
>>> (utcnow - then).days
31
I created a utcnow variable in the above example based of the UTC timezone before calculating how long ago the parsed date was.