Str To Time Object In Python 3
Solution 1:
A timezone without a date is meaningless, so no, you can't use both to produce a time
object. While the standard library time
object does support having a tzinfo
attribute, the 'timezone' object is not really a timezone, but merely a time offset.
A timezone is more than just an offset from UTC. Timezone offsets are date-dependent, and because such details as the Daylight Savings winter / summer time distinction is partly the result of political decisions, what dates the timezone offset changes is also dependent on the year.
To be explicit, America/New_York
is a timezone, not a time offset. The exact offset from UTC depends on the date; it'll be minus 4 hours in summer, 5 hours in winter!
So for a timezone such as America/New_York
, you need to pick a date too. If you don't care about the date, pick a fixed date so your offset is at least consistent. If you are converting a lot of time stamps, store the timezone offset once as a timedelta()
, then use that timedelta to shift time()
objects to the right offset.
To parse just a timestring, pretend there is a date attached by using the datetime.strptime()
method, then extract the time object:
from datetime import datetime
try:
timeobject = datetime.strptime(time_str, '%H:%M').time()
except ValueError:
# input includes seconds, perhaps
timeobject = datetime.strptime(time_str, '%H:%M:%S').time()
To update the time given a timezone, get a timezone database that supports your timezone string first; the pytz
library is regularly updated.
from pytz importtimezonetimezone= pytz.timezone(time_zone_str)
How you use it depends on what you are trying to do. If the input time is not in UTC, you can simply attach the timezone to a datetime()
object with the datetime.combine()
method, after which you can move it to the UTC timezone:
dt_in_timezone = datetime.combine(datetime.now(), timeobject, timezone)
utc_timeobject = dt_in_timezone.astimezone(pytz.UTC).time()
This assumes that 'today' is good enough to determine the correct offset.
If your time is a UTC timestamp, combine it with the UTC
timezone, then use the pytz timezone; effectively the reverse:
dt_in_utc = datetime.combine(datetime.now(), timeobject, pytz.UTC)
timeobject_in_timezone = dt_in_timezone.astimezone(timezone).time()
To store just the offset for bulk application, pass in a reference date to the timezone.utcoffset()
method:
utc_offset = timezone.utcoffset(datetime.now())
after which you can add this to any datetime
object as needed to move from UTC to local time, or subtract it to go from local to UTC. Note that I said datetime
, as time
objects also don't support timedelta
arithmetic; a timedelta can be larger than the number of seconds left in the day or the number of seconds since midnight, after all, so adding or subtracting could shift days as well as the time:
# newtime after shifting
(datetime.combine(datetime.now(), timeobject) + utc_offset).time()
For completion sake, you can't pass in a pytz timezone to a time
object; it just doesn't have any effect on the time. The timezone object returns None
for the UTC offset in that case, because it can't give any meaningful answer without a date:
>>>from datetime import time>>>from pytz import timezone>>>tz = timezone('America/New_York')>>>time_with_zone = time(12, 34, tzinfo=tz)>>>time_with_zone
datetime.time(12, 34, tzinfo=<DstTzInfo 'America/New_York' LMT-1 day, 19:04:00 STD>)
>>>time_with_zone.utcoffset()>>>time_with_zone.utcoffset() isNone
True
>>>tz.utcoffset(None) isNone# what time_with_zone.utcoffset() does under the hood
None
So for all intents an purposes, time_with_zone
is just another naive time object as the tzinfo
object attached doesn't actually have any effect.
Moreover, because there is no date to determine the correct timezone information, pytz selects the earliest known 'New York' timezone, and that's not exactly a recent one; look closely at that tzinfo
representation:
tzinfo=<DstTzInfo 'America/New_York' LMT-1day, 19:04:00 STD>^^^^^^^^^^^^^^^^^^^^^^^
That's the timezone introduced in 1883 by the railroads; the 'modern' EST timezone was not introduced until the 20th century. This is why timezone objects are usually passed in a date when determining the offset:
>>>tz.utcoffset(datetime(1883, 6, 28))
datetime.timedelta(-1, 68640)
>>>tz.utcoffset(datetime(1918, 6, 28))
datetime.timedelta(-1, 72000)
Solution 2:
The answer to "can I do this?" (with a timezone) is both yes and no. Firstly let's convert the string to a time
object. As one commenter mentioned, you can do this in python 3.7 with the fromisoformat
method:
from datetime import time
time.fromisoformat("09:30")
If you are not using 3.7, you can do this by creating a datetime
and then converting to a time object
:
from datetime import datetime, time
as_time = datetime.datetime.strptime("09:00", "%H:%M").time()
Now to deal with the timezone. As the timezone is a name, we can use the very convenient pytz module to convert it to a tzinfo object:
pytz.timezone('America/New_York')
At this point you're probably tempted to just pass it to the time constructor as the tzinfo argument, but unfortunately that does not work with pytz:
Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones. ~ http://pytz.sourceforge.net/
So we will have to use the localize
method of the newly created tzinfo object. But unfortunately we will still not be able to successfully localize the time
object with this timezone. The reason for this is that pytz needs to know the date in order to determine if this timezone is in daylight savings time or not. As we have not provided the date, achieving this is quite impossible and you will get odd results like:
>>> pytz.timezone('America/New_York').localize(as_dt).isoformat()
'1900-01-01T09:00:00-04:56'
Note the -04:56
offset, which is gibberish. There are a few options for getting to what you ultimately want.
One option is to assume the time is a time today:
as_time = datetime.datetime.strptime("09:00", "%H:%M").time()
tz = pytz.timezone('America/New_York')
local_time = tz.localize(datetime.datetime.now().replace(hour=as_time.hour, minute=as_time.minute))
The other option is to use naive timezone offsets rather than timezone names:
from datetime import timezone, timedeltanaive_tz= timezone(timedelta(hours=5))
datetime.time(9, 30).replace(tz_info=naive_tz)
But I would not recommend this method as it's quite brittle and would require some intermediate steps to derive from the TZ location name that are non-trivial.
Solution 3:
Hope it works for you,
import datetime
# Hello World program in Pythonprint"Hello World!\n"
time_str = '09:30'
time_zone_str = 'America/New_York'
s = "I am looking for a course in Paris!"print(s)
print(datetime.datetime.strptime(time_str, '%H:%M').time())
print(datetime.time(3, 55))
Thanks
Post a Comment for "Str To Time Object In Python 3"