28

We have a server that runs on GMT time. I need to write a Python script that determines if it's currently (at this very second) Daylight Savings Time (DST) in Los Angeles, CA. How can I accomplish this? I took a look at pytz and time, but I can't figure it out. I realize that I could create some logic such as comparing the current time in LA to GMT time, but it would be a lot cleaner if I could use a standard library instead.

Thanks

Edit: Here's some sample code of me setting up the timezone:

from pytz import timezone
import pytz
from datetime import datetime, timedelta

tz = timezone('America/Los_Angeles')
// Instantiate a datetime object using tz? 

Edit: Here's a snippet of code that will work. It's not elegant, which is why I'm asking if there's a library or something that is made for this. Maybe like a is_dst() function.

utc = timezone("UTC")
now = utc.localize(datetime.utcnow())
los_angeles_tz = timezone('America/Los_Angeles')
los_angeles_time = now.astimezone(los_angeles_tz)

delta = los_angeles_time.utcoffset()
dstDelta = timedelta(hours=-8)

is_dst = (delta == dstDelta)
Joey Mason
  • 707
  • 1
  • 8
  • 15
  • 1
    http://stackoverflow.com/questions/7986776/how-do-you-convert-a-naive-datetime-to-dst-aware-datetime-in-python – kgu87 Nov 04 '13 at 18:42
  • 4
    @Marcin to be fair - it's not the most friendly area of Python's library to have a stab at attempting a solution with. So while technically off-topic, it's not exactly an unreasonable question. – Jon Clements Nov 04 '13 at 18:57
  • 2
    @JonClements Perhaps so, but it would be nice to see something that demonstrates OP went beyond opening the docs and saying "gosh this looks hard, maybe someone on SO can solve my problem". – Marcin Nov 04 '13 at 19:16
  • related: [Python daylight savings time](http://stackoverflow.com/questions/2881025/python-daylight-savings-time) – jfs Jul 01 '15 at 00:42

2 Answers2

43
import pytz
from datetime import datetime, timedelta

def is_dst(zonename):
    tz = pytz.timezone(zonename)
    now = pytz.utc.localize(datetime.utcnow())
    return now.astimezone(tz).dst() != timedelta(0)

Usage:

>>> is_dst("America/Los_Angeles")
False

>>> is_dst("America/Sao_Paulo")
True
Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • 1
    @user1615497: you could use `datetime.now(tz)` to get the current time in `tz` timezone e.g., [`is_dst = lambda zonename: bool(datetime.now(pytz.timezone(zonename)).dst())`](http://stackoverflow.com/a/19968515/4279) – jfs Sep 15 '14 at 00:02
  • 3
    @J.F.Sebastian - pytz docs make it clear that `localize` needs to be used; that passing a pytz time zone to the tzinfo parameter of a `datetime` is not sufficient. Is this wrong? – Matt Johnson-Pint Sep 15 '14 at 04:40
  • 1
    it is wrong for now(tz) in general and UTC timezone in particular. now() is documented to call tz.fromutc() that is overridden by pytz timezone to do the right thing (use _utc_transition_times to get valid tzinfo). In addition, UTC is a special case: zero UTC offset, always – jfs Sep 15 '14 at 04:54
  • More: [when does `datetime.now(pytz_timezone)` fail?](https://stackoverflow.com/q/31886808/4279) – jfs Aug 17 '17 at 14:47
12
from datetime import datetime
import pytz

isdst_now_in = lambda zonename: bool(datetime.now(pytz.timezone(zonename)).dst())

Example:

>>> isdst_now_in("America/Los_Angeles") # 2014-10-27 12:32:07 PDT-0700
True
>>> isdst_now_in("Australia/Melbourne") # 2014-10-28 06:32:07 AEDT+1100
True

Here's stdlib-only version on Unix using time.tzset() function:

import os
import time
from contextlib import contextmanager

@contextmanager
def local_timezone(zonename):
    #NOTE: it manipulates global state
    oldname = os.environ.get('TZ')
    try:
        os.environ['TZ'] = zonename
        time.tzset()
        yield
    finally:
        if oldname is None:
           del os.environ['TZ']
        else:
           os.environ['TZ'] = oldname
        time.tzset()

def time_isdst_now_in(zonename):
    with local_timezone(zonename):
         return time.localtime().tm_isdst > 0

The usage is the same:

>>> time_isdst_now_in('Europe/London') # 2014-04-17 18:42:11 BST+0100
True

Note: time.daylight is not used due to issues in some edge cases.

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