Python - Setting a datetime in a specific timezone (without UTC conversions)
Asked Answered
F

2

35

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.)

First answered 11/2, 2011 at 22:27 Comment(3)
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?Moorer
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.First
#4563772Keldon
G
23

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).

Geneva answered 11/2, 2011 at 23:1 Comment(12)
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.First
@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.Geneva
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.First
From pytz docs: """Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones."""Sternberg
@J.F.Sebastian can you put the correct way if you're going to say both of the examples are XXX: WRONG?Methedrine
@NickT sure. Here's my answer from 2015.Palembang
@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?Geneva
@MarkRansom there is explicit comment: it fails for any local time zone with a non-zero utc offset.Palembang
@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?Geneva
@MarkRansom run your code (the code in your answer) on any machine where the local time zone (tzlocal.get_localzone()) is not utc.Palembang
@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?Geneva
@MarkRansom: do you see strftime('%s') in the code in your answer? Your code produces 1297504800 (TZ=US/Central). It should return 1297483200.Palembang
P
26

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).

Palembang answered 4/9, 2014 at 11:58 Comment(0)
G
23

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).

Geneva answered 11/2, 2011 at 23:1 Comment(12)
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.First
@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.Geneva
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.First
From pytz docs: """Unfortunately using the tzinfo argument of the standard datetime constructors ‘’does not work’’ with pytz for many timezones."""Sternberg
@J.F.Sebastian can you put the correct way if you're going to say both of the examples are XXX: WRONG?Methedrine
@NickT sure. Here's my answer from 2015.Palembang
@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?Geneva
@MarkRansom there is explicit comment: it fails for any local time zone with a non-zero utc offset.Palembang
@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?Geneva
@MarkRansom run your code (the code in your answer) on any machine where the local time zone (tzlocal.get_localzone()) is not utc.Palembang
@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?Geneva
@MarkRansom: do you see strftime('%s') in the code in your answer? Your code produces 1297504800 (TZ=US/Central). It should return 1297483200.Palembang

© 2022 - 2024 — McMap. All rights reserved.