44

How do I properly represent a different timezone in my timezone? The below example only works because I know that EDT is one hour ahead of me, so I can uncomment the subtraction of myTimeZone()

import datetime, re
from datetime import tzinfo

class myTimeZone(tzinfo):
    """docstring for myTimeZone"""
    def utfoffset(self, dt):
        return timedelta(hours=1)

def myDateHandler(aDateString):
    """u'Sat,  6 Sep 2008 21:16:33 EDT'"""
    _my_date_pattern = re.compile(r'\w+\,\s+(\d+)\s+(\w+)\s+(\d+)\s+(\d+)\:(\d+)\:(\d+)')
    day, month, year, hour, minute, second = _my_date_pattern.search(aDateString).groups()
    month = [
            'JAN', 'FEB', 'MAR', 
            'APR', 'MAY', 'JUN', 
            'JUL', 'AUG', 'SEP', 
            'OCT', 'NOV', 'DEC'
    ].index(month.upper()) + 1
    dt = datetime.datetime(
        int(year), int(month), int(day), 
        int(hour), int(minute), int(second)
    )                   
    # dt = dt - datetime.timedelta(hours=1)
    # dt = dt - dt.tzinfo.utfoffset(myTimeZone())
    return (dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second, 0, 0, 0)

def main():
    print myDateHandler("Sat,  6 Sep 2008 21:16:33 EDT")

if __name__ == '__main__':
    main()
jidar
  • 551
  • 1
  • 4
  • 9
  • Take a look at [this answer](http://stackoverflow.com/a/18646797/2697658). Hope it helps! – juan Sep 05 '13 at 22:19
  • your specific date/time format can be handled using `email.utils` stdlib package: [`ts = mktime_tz(parsedate_tz('Sat, 6 Sep 2008 21:16:33 EDT'))`](http://stackoverflow.com/a/23117071/4279) – jfs Jan 01 '16 at 02:29

4 Answers4

39

I recommend babel and pytz when working with timezones. Keep your internal datetime objects naive and in UTC and convert to your timezone for formatting only. The reason why you probably want naive objects (objects without timezone information) is that many libraries and database adapters have no idea about timezones.

gerrit
  • 24,025
  • 17
  • 97
  • 170
Armin Ronacher
  • 31,998
  • 13
  • 65
  • 69
  • Please update the Babel's link to http://babel.pocoo.org/ (as the old website says) – saeedgnu Aug 12 '13 at 16:50
  • Also notice that babel is on top of pytz – saeedgnu Aug 12 '13 at 17:14
  • Isn't it a contradiction to say "naive and in UTC" – tadasajon Mar 11 '14 at 14:25
  • @JonCrowell: naive datetime object has no timezone information. You can interpret it as a time in any timezone (it is ambiguous in other words) including UTC e.g., you could treat `2008-09-22 20:59:00` as time in UTC (it is `2008-09-22 13:59:00 PDT-0700`). – jfs Sep 04 '14 at 12:26
11

The Python standard library doesn't contain timezone information, because unfortunately timezone data changes a lot faster than Python. You need a third-party module for this; the usual choice is pytz

Thomas Wouters
  • 130,178
  • 23
  • 148
  • 122
  • 1
    That doesn't explain why the standard library can't handle -500 though. – Bradley Kreider Aug 06 '12 at 21:19
  • 5
    That's not a valid reason. The standard library could use resources on the platform it's running on if available and gracefully degrade if time zone history was not found. – Prof. Falken Sep 24 '12 at 14:17
  • @Prof.Falken: how would you gracefully degrade if the timezone info is not available (raise exceptions, return (possibly) wrong results, both)? btw, see [PEP 431: Time zone support improvements](http://legacy.python.org/dev/peps/pep-0431/) – jfs Sep 04 '14 at 12:29
  • @J.F.Sebastian, I don't know. Exceptions come to mind but I am no Python expert. It just seems to me that things could be better than they are. PEP 431 looks like a good start to me. – Prof. Falken Sep 04 '14 at 12:45
7

For the current local timezone, you can you use:

>>> import time
>>> offset = time.timezone if (time.localtime().tm_isdst == 0) else time.altzone
>>> offset / 60 / 60 * -1
-9

The value returned is in seconds West of UTC (with areas East of UTC getting a negative value). This is the opposite to how we'd actually like it, hence the * -1.

localtime().tm_isdst will be zero if daylight savings is currently not in effect (although this may not be correct if an area has recently changed their daylight savings law).

Scrool
  • 168
  • 1
  • 5
Carlos H Romano
  • 616
  • 6
  • 9
  • [`time.timezone` and `time.altzone` is not enough in some cases](http://stackoverflow.com/q/3168096/4279) – jfs Jul 09 '15 at 00:15
2

Python >= 3.9

Python comes with zoneinfo as part of the standard lib. Example usage:

from datetime import datetime, timezone
from zoneinfo import ZoneInfo
UTC = datetime(2012,11,10,9,0,0, tzinfo=timezone.utc)

# convert to another tz with "astimezone":
eastern = UTC.astimezone(ZoneInfo("US/Eastern"))

# note that it is safe to use "replace",
# to get the same wall time in a different tz:
pacific = eastern.replace(tzinfo=ZoneInfo("US/Pacific"))

print(UTC.isoformat())
print(eastern.isoformat())
print(pacific.isoformat())

# 2012-11-10T09:00:00+00:00
# 2012-11-10T04:00:00-05:00
# 2012-11-10T04:00:00-08:00

Also note this section from the docs:

The zoneinfo module does not directly provide time zone data, and instead pulls time zone information from the system time zone database or the first-party PyPI package tzdata, if available.

So don't forget to call a pip install tzdata, on Windows at least.

FObersteiner
  • 22,500
  • 8
  • 42
  • 72