Kuba
Kuba

Reputation: 936

Getting yesterdays date with time zone

Hi I was able to find the answer to this question but not with the timezone included (http://stackoverflow.com/questions/1712116/formatting-yesterdays-date-in-python)

This is working fine for me:

>>> import time
>>> time.strftime('/%Z/%Y/%m/%d')
'/EST/2013/01/18'

but is there a way to get the yesterdays date? I need to handle the timezone change when we switch from EST to EDT, EDT to EST

datetime modules allows to use timedelta, but the naive object don't support timezones by default and I'm not sure how to handle that.

Upvotes: 1

Views: 3881

Answers (2)

siddharthlatest
siddharthlatest

Reputation: 2257

For accounting timezone and daylight saving time changes, the datetime.datetime object needs to be timezone aware, i.e. tzinfo property should not be None. This can be done by subclassing the tzinfo abstract class. The ustimezone module does exactly that.

>>> import ustimezone
>>> from datetime import datetime, tzinfo, timedelta
>>> yesterday = datetime.now() - timedelta(days=1)
>>> yesterday
datetime.datetime(2013, 1, 17, 18, 24, 22, 106445)
>>> yesterday_aware = yesterday.replace(tzinfo=ustimezone.Eastern)
>>> yesterday.strftime('%Z/%Y/%m/%d')
'EST/2013/01/17'    # Will show EDT/EST depending on dst being present or not.

The dst information is captured by the tm_isdst value of the timetuple.

>>> yesterday_aware.timetuple()
time.struct_time(tm_year=2013, tm_mon=1, tm_mday=17, tm_hour=18, tm_min=24, tm_sec=22, tm_wday=3, tm_yday=17, tm_isdst=0)
>>> _.tm_isdst
>>> 0    # the tm_isdst flag of the time tuple can be used for checking if DST is present or not.

The ustimezone module here looks something like this (Borrowed from an example in Python datetime reference)

from datetime import datetime, tzinfo, timedelta

ZERO = timedelta(0)
HOUR = timedelta(hours=1)

# A complete implementation of current DST rules for major US time zones.

def first_sunday_on_or_after(dt):
    days_to_go = 6 - dt.weekday()
    if days_to_go:
        dt += timedelta(days_to_go)
    return dt


# US DST Rules
#
# This is a simplified (i.e., wrong for a few cases) set of rules for US
# DST start and end times. For a complete and up-to-date set of DST rules
# and timezone definitions, visit the Olson Database (or try pytz):
# http://www.twinsun.com/tz/tz-link.htm
# http://sourceforge.net/projects/pytz/ (might not be up-to-date)
#
# In the US, since 2007, DST starts at 2am (standard time) on the second
# Sunday in March, which is the first Sunday on or after Mar 8.
DSTSTART_2007 = datetime(1, 3, 8, 2)
# and ends at 2am (DST time; 1am standard time) on the first Sunday of Nov.
DSTEND_2007 = datetime(1, 11, 1, 1)
# From 1987 to 2006, DST used to start at 2am (standard time) on the first
# Sunday in April and to end at 2am (DST time; 1am standard time) on the last
# Sunday of October, which is the first Sunday on or after Oct 25.
DSTSTART_1987_2006 = datetime(1, 4, 1, 2)
DSTEND_1987_2006 = datetime(1, 10, 25, 1)
# From 1967 to 1986, DST used to start at 2am (standard time) on the last
# Sunday in April (the one on or after April 24) and to end at 2am (DST time;
# 1am standard time) on the last Sunday of October, which is the first Sunday
# on or after Oct 25.
DSTSTART_1967_1986 = datetime(1, 4, 24, 2)
DSTEND_1967_1986 = DSTEND_1987_2006

class USTimeZone(tzinfo):

    def __init__(self, hours, reprname, stdname, dstname):
        self.stdoffset = timedelta(hours=hours)
        self.reprname = reprname
        self.stdname = stdname
        self.dstname = dstname

    def __repr__(self):
        return self.reprname

    def tzname(self, dt):
        if self.dst(dt):
            return self.dstname
        else:
            return self.stdname

    def utcoffset(self, dt):
        return self.stdoffset + self.dst(dt)

    def dst(self, dt):
        if dt is None or dt.tzinfo is None:
            # An exception may be sensible here, in one or both cases.
            # It depends on how you want to treat them.  The default
            # fromutc() implementation (called by the default astimezone()
            # implementation) passes a datetime with dt.tzinfo is self.
            return ZERO
        assert dt.tzinfo is self

        # Find start and end times for US DST. For years before 1967, return
        # ZERO for no DST.
        if 2006 < dt.year:
            dststart, dstend = DSTSTART_2007, DSTEND_2007
        elif 1986 < dt.year < 2007:
            dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
        elif 1966 < dt.year < 1987:
            dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
        else:
            return ZERO

        start = first_sunday_on_or_after(dststart.replace(year=dt.year))
        end = first_sunday_on_or_after(dstend.replace(year=dt.year))

        # Can't compare naive to aware objects, so strip the timezone from
        # dt first.
        if start <= dt.replace(tzinfo=None) < end:
            return HOUR
        else:
            return ZERO

Eastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")

Upvotes: 0

cptPH
cptPH

Reputation: 2401

the do it yourself method, but i don't know if there is a better method

>>> import time
>>> from datetime import date, timedelta
>>> yesterday = date.today() - timedelta(1)
>>> yesterday = yesterday.strftime('%Y/%m/%d')
>>> yesterday = "/%s/%s" % ( time.tzname[0], yesterday )
>>> print yesterday
'/CET/2013/01/17'

Upvotes: 1

Related Questions