33

Just to be clear, this is python 2.6, I am using pytz.

This is for an application that only deals with US timezones, I need to be able to anchor a date (today), and get a unix timestamp (epoch time) for 8pm and 11pm in PST only.

This is driving me crazy.

> pacific = pytz.timezone("US/Pacific")

> datetime(2011,2,11,20,0,0,0,pacific)

datetime.datetime(2011, 2, 11, 20, 0, tzinfo=<DstTzInfo 'US/Pacific' PST-1 day, 16:00:0 STD>)

> datetime(2011,2,11,20,0,0,0,pacific).strftime("%s")
'1297454400'

zsh> date -d '@1297454400'    
Fri Feb 11 12:00:00 PST 2011

So, even though I am setting up a timezone, and creating the datetime with that time zone, it is still creating it as UTC and then converting it. This is more of a problem since UTC will be a day ahead when I am trying to do the calculations.

Is there an easy (or at least sensical) way to generate a timestamp for 8pm PST today?

(to be clear, I do understand the value of using UTC in most situations, like database timestamps, or for general storage. This is not one of those situations, I specifically need a timestamp for evening in PST, and UTC should not have to enter into it.)

liam
  • 3,830
  • 6
  • 32
  • 31
  • What is the issue here - the end date you have is Fri Feb 11 12:00:00 PST 2011 and the start date is 11th Feb? – mmmmmm Feb 11 '11 at 22:45
  • The issue is that I am trying to create a datetime for 8pm PST, and it is creating it for 8PM UTC and printing it as noon. I seriously just want to make an object for "8PM PST TODAY" and generate a unix timestamp, without having to do a bunch of UTC manipulations. – liam Feb 11 '11 at 22:59
  • http://stackoverflow.com/questions/4563272/convert-a-python-utc-datetime-to-a-local-datetime-using-only-python-standard-lib – Wtower Dec 23 '16 at 18:17

2 Answers2

25

There are at least two issues:

  1. you shouldn't pass a timezone with non-fixed UTC offset such as "US/Pacific" as tzinfo parameter directly. You should use pytz.timezone("US/Pacific").localize() method instead
  2. .strftime('%s') is not portable, it ignores tzinfo, and it always uses the local timezone. Use datetime.timestamp() or its analogs on older Python versions instead.

To make a timezone-aware datetime in the given timezone:

#!/usr/bin/env python
from datetime import datetime 
import pytz # $ pip install pytz

tz = pytz.timezone("US/Pacific")
aware = tz.localize(datetime(2011, 2, 11, 20), is_dst=None)

To get POSIX timestamp:

timestamp = (aware - datetime(1970, 1, 1, tzinfo=pytz.utc)).total_seconds()

(On Python 2.6, see totimestamp() function on how to emulate .total_seconds() method).

Community
  • 1
  • 1
jfs
  • 399,953
  • 195
  • 994
  • 1,670
21

Create a tzinfo object utc for the UTC time zone, then try this:

#XXX: WRONG (for any timezone with a non-fixed utc offset), DON'T DO IT
datetime(2011,2,11,20,0,0,0,pacific).astimezone(utc).strftime("%s")

Edit: As pointed out in the comments, putting the timezone into the datetime constructor isn't always robust. The preferred method using the pytz documentation would be:

pacific.localize(datetime(2011,2,11,20,0,0,0)).astimezone(utc).strftime("%s")

Also note from the comments that strftime("%s") isn't reliable, it ignores the time zone information (even UTC) and assumes the time zone of the system it's running on. It relies on an underlying C library implementation and doesn't work at all on some systems (e.g. Windows).

Mark Ransom
  • 299,747
  • 42
  • 398
  • 622
  • Actually, that only worked in the open interpreter I had, its now returning the wrong result once I moved it to script. Ill keep hammering away at it, though. – liam Feb 11 '11 at 23:09
  • @liam, the time zone support in Python has always seemed half-baked to me. The problem in this case is that Unix/Linux dates are always UTC-based, even when displayed in your local time zone, and you need to adjust the Python date to be likewise. – Mark Ransom Feb 11 '11 at 23:10
  • Yeah, the issue was that I was running it in the interactive shell, and had already called tzset() (i think, i can't find the reference now), on PST. This did some screwy thing where PST was treated as UTC and screwed up all the pytz calculations. "Half-baked" is an understatement, I am amazed at how pointlessly confusing the datetime library is, considering how clean most of the built-in libraries are. – liam Feb 17 '11 at 19:41
  • 1
    From pytz docs: """Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones.""" – Doncho Gunchev Oct 09 '12 at 15:53
  • @J.F.Sebastian can you put the correct way if you're going to say both of the examples are `XXX: WRONG`? – Nick T Nov 04 '16 at 16:26
  • @NickT sure. Here's [my answer from 2015](http://stackoverflow.com/a/25664904/4279). – jfs Nov 04 '16 at 16:33
  • @J.F.Sebastian I understand why my first example doesn't work, I've seen questions that provide ample evidence of that form breaking. But can you name a situation where the second one doesn't work? – Mark Ransom Nov 04 '16 at 17:34
  • @MarkRansom there is explicit comment: it fails for any local time zone with a non-zero utc offset. – jfs Nov 04 '16 at 18:31
  • @J.F.Sebastian I just tried it, converting Pacific to Central, for dates both with DST and without DST. It worked perfectly. Do you have a *specific example*? – Mark Ransom Nov 04 '16 at 18:45
  • @MarkRansom run your code (the code in your answer) on any machine where the local time zone (`tzlocal.get_localzone()`) is not utc. – jfs Nov 04 '16 at 18:49
  • @J.F.Sebastian As I said, I ran the conversion myself on my system which is in the US Central time zone. Unfortunately I couldn't include the `strftime` because my environment is Python 2.7 on Windows, which doesn't support `%s`. Is that the part which fails? – Mark Ransom Nov 04 '16 at 19:02
  • @MarkRansom: do you see `strftime('%s')` in the code in your answer? Your code produces `1297504800` (`TZ=US/Central`). It should return `1297483200`. – jfs Nov 04 '16 at 19:21