Reputation: 305
I'm attempting to convert a given string to Unix time. The string always has a time in it and optionally has a date with it as well. For example, 12/31/15 11:59PM
, 12/31/15 11:59
, and 11:59
are strings that I can expect to get.
Using the following, any of those strings gets converted correctly:
from dateutil import parser
import time
timezone = "12/31/15 11:59"
target = time.mktime(parser.parse(timestamp).timetuple())
However, if given a timezone as well, e.g. 12/31/15 11:59PM PST
, the timezone gets dropped by timetuple()
and while the conversion works, it will still give the same result as if the timezone weren't in the string (and thus is correct only for the local time of the system).
I haven't found an elegant way to 1) properly convert the string to the appropriate timezone when a timezone is given and at the same time 2) allow for the timezone string to be present, or if missing just assume local timezone.
Upvotes: 1
Views: 1087
Reputation: 414795
The input time string may be ambiguous:
11:59
: the utc offset may depend on the date e.g., it may be different during the summer time. To disambiguate the date, you could pass default
parameter to the .parse()
methodPST
may correspond to different timezones. To disambiguate the utc offset, you could pass tzinfos
parametermktime()
may fail on some systems or during a DST transition. tzlocal
enables a portable solution:
#!/usr/bin/env python
from datetime import datetime
from dateutil.parser import parse # $ pip install python-dateutil
from pytz import utc # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
epoch = datetime(1970, 1, 1, tzinfo=utc) # POSIX Epoch
default = datetime(2016, 1, 1)
tzinfos = dict(PST=-8 * 3600)
tz = get_localzone() # local timezone
for time_string in ["12/31/15 11:59PM", "12/31/15 11:59PM PST", "12/31/15 11:59",
"11:59"]:
dt = parse(time_string, default=default, tzinfos=tzinfos)
if dt.tzinfo is None or dt.utcoffset() is None: # naive
dt = tz.normalize(tz.localize(dt)) # assume local timezone
posix_timestamp = (dt - epoch).total_seconds()
dt = datetime.fromtimestamp(posix_timestamp, dt.tzinfo)
print("{dt} <- {posix_timestamp:.0f} <- {time_string}".format(**vars()))
2015-12-31 23:59:00+01:00 <- 1451602740 <- 12/31/15 11:59PM
2015-12-31 23:59:00-08:00 <- 1451635140 <- 12/31/15 11:59PM PST
2015-12-31 11:59:00+01:00 <- 1451559540 <- 12/31/15 11:59
2016-01-01 11:59:00+01:00 <- 1451645940 <- 11:59
tz.localize()
uses is_dst=False
, to disambiguate time during DST transitions or for non-existent local times, see "Can I just always set is_dst=True?" section.
Upvotes: 1