1

How can I take this date string:

"2015-01-01"

and, assuming it is in a specific timezone (say, "US-Mountain"), convert it to a POSIX timestamp?

Like so:

magic_parse_function("2015-01-01", pytz.timezone("US-Mountain")) -> 1420095600

I've spent quite some time scouring the docs and this site, playing with aware/unaware datetime objects, and am hoping for a not-too-crazy solution. The following does not work, the last two lines of output are identical, and they should be 3600 seconds apart:

import datetime
import time
import pytz
timestring = "2015-01-01"
pacific = pytz.timezone("US/Pacific")
mountain = pytz.timezone("US/Mountain")
(year, month, day) = timestring.split('-')
year = int(year)
month = int(month)
day = int(day)
unaware = datetime.datetime(year, month, day, 0, 0, 0, 0)
# aware_pacific = pacific.localize(unaware)
# aware_mountain = mountain.localize(unaware)
aware_mountain = unaware.replace(tzinfo=mountain)
aware_pacific = unaware.replace(tzinfo=pacific)
print time.mktime(aware_pacific.timetuple())
print time.mktime(aware_mountain.timetuple())
shiftycow
  • 232
  • 2
  • 11
  • 1
    Assuming midnight isn't necessarily the right thing to do. Not every time zone *has* a local midnight on every day. Some (like Brazil) skip from 23:59:59 to 01:00:00 on the DST spring-forward day. – Matt Johnson-Pint Nov 21 '15 at 05:07
  • Also, it looks like you had the solution, using `localize`. Why did you comment it out and go with replace? – Matt Johnson-Pint Nov 21 '15 at 05:12
  • localize() vs. replace() doesn't have an affect on the output. I think the issue is that timetuple() throws away the timezone information, so I'm hoping someone can tell me an alternate (i.e. elegant) way to get the timestamp out of the aware datetime object. – shiftycow Nov 21 '15 at 05:44
  • 1
    `.replace()` is incorrect. See [Datetime Timezone conversion using pytz](http://stackoverflow.com/q/27531718/4279) – jfs Nov 21 '15 at 10:00
  • 1
    related to your specific input: [How to get the first datetime of a day?](http://stackoverflow.com/q/27770504/4279) – jfs Nov 21 '15 at 10:02

1 Answers1

4

There are three steps:

  1. Convert the date string into a naive datetime object:

    from datetime import datetime 
    
    dt = datetime(*map(int ,'2015-01-01'.split('-')))
    
  2. Get a timezone-aware datetime object:

    import pytz # $ pip install pytz
    
    aware = pytz.timezone("US/Mountain").localize(dt, is_dst=None)
    

    is_dst=None raises an exception for ambiguous or non-existing times. Here're more details about what is is_dst flag and why do you need it, see "Can I just always set is_dst=True?" section

  3. Get POSIX timestamp:

    timestamp = aware.timestamp()
    

    .timestamp() is available since Python 3.3+. See multiple solutions for older Python versions.

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
  • It may be preferable to do `datetime.strptime("2015-01-01", "%Y-%m-%d")` instead of `datetime(*map(int ,'2015-01-01'.split('-')))`. – Trey Hunner Nov 22 '15 at 20:36
  • @TreyHunner: `.strptime()` is more powerfull and more precise. It should be used in general. For this example, I've chosen a simpler (more intelligible error messages e.g., pass `'2015-01-32'`) more explicit and more efficient code that doesn't require OP to know strftime format codes. – jfs Nov 23 '15 at 04:46
  • I wound up using the timedelta solution to get the UNIX timestamp in the linked answer. I was hoping for something less "ugly", but I guess I'll have to upgrade to Python3 for that. Also, I do use strptime in the actual implementation. The *map thing is a cool trick, though. – shiftycow Nov 24 '15 at 22:27