How to make an unaware datetime timezone aware in python

前端 未结 12 2078
一向
一向 2020-11-22 08:39

What I need to do

I have a timezone-unaware datetime object, to which I need to add a time zone in order to be able to compare it with other timezon

相关标签:
12条回答
  • 2020-11-22 08:48

    I use this statement in Django to convert an unaware time to an aware:

    from django.utils import timezone
    
    dt_aware = timezone.make_aware(dt_unaware, timezone.get_current_timezone())
    
    0 讨论(0)
  • 2020-11-22 08:48

    Python 3.9 adds the zoneinfo module so now only the standard library is needed!

    from zoneinfo import ZoneInfo
    from datetime import datetime
    unaware = datetime(2020, 10, 31, 12)
    

    Attach a timezone:

    >>> unaware.replace(tzinfo=ZoneInfo('Asia/Tokyo'))
    datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='Asia/Tokyo'))
    >>> str(_)
    '2020-10-31 12:00:00+09:00'
    

    Attach the system's local timezone:

    >>> unaware.replace(tzinfo=ZoneInfo('localtime'))
    datetime.datetime(2020, 10, 31, 12, 0, tzinfo=zoneinfo.ZoneInfo(key='localtime'))
    >>> str(_)
    '2020-10-31 12:00:00+01:00'
    

    Subsequently it is properly converted to other timezones:

    >>> unaware.replace(tzinfo=ZoneInfo('localtime')).astimezone(ZoneInfo('Asia/Tokyo'))
    datetime.datetime(2020, 10, 31, 20, 0, tzinfo=backports.zoneinfo.ZoneInfo(key='Asia/Tokyo'))
    >>> str(_)
    '2020-10-31 20:00:00+09:00'
    

    Wikipedia list of available time zones


    Windows has no system time zone database, so here an extra package is needed:

    pip install tzdata  
    

    There is a backport to allow use of zoneinfo in Python 3.6 to 3.8:

    pip install backports.zoneinfo
    

    Then:

    from backports.zoneinfo import ZoneInfo
    
    0 讨论(0)
  • 2020-11-22 08:48

    for those that just want to make a timezone aware datetime

    import datetime
    import pytz
    
    datetime.datetime(2019, 12, 7, tzinfo=pytz.UTC)
    
    0 讨论(0)
  • 2020-11-22 08:50

    All of these examples use an external module, but you can achieve the same result using just the datetime module, as also presented in this SO answer:

    from datetime import datetime
    from datetime import timezone
    
    dt = datetime.now()
    dt.replace(tzinfo=timezone.utc)
    
    print(dt.replace(tzinfo=timezone.utc).isoformat())
    '2017-01-12T22:11:31+00:00'
    

    Fewer dependencies and no pytz issues.

    NOTE: If you wish to use this with python3 and python2, you can use this as well for the timezone import (hardcoded for UTC):

    try:
        from datetime import timezone
        utc = timezone.utc
    except ImportError:
        #Hi there python2 user
        class UTC(tzinfo):
            def utcoffset(self, dt):
                return timedelta(0)
            def tzname(self, dt):
                return "UTC"
            def dst(self, dt):
                return timedelta(0)
        utc = UTC()
    
    0 讨论(0)
  • 2020-11-22 08:59

    I wrote this at Nov 22 2011 , is Pyhton 2 only , never checked if it work on Python 3

    I had use from dt_aware to dt_unaware

    dt_unaware = dt_aware.replace(tzinfo=None)
    

    and dt_unware to dt_aware

    from pytz import timezone
    localtz = timezone('Europe/Lisbon')
    dt_aware = localtz.localize(dt_unware)
    

    but answer before is also a good solution.

    0 讨论(0)
  • 2020-11-22 09:01

    I agree with the previous answers, and is fine if you are ok to start in UTC. But I think it is also a common scenario for people to work with a tz aware value that has a datetime that has a non UTC local timezone.

    If you were to just go by name, one would probably infer replace() will be applicable and produce the right datetime aware object. This is not the case.

    the replace( tzinfo=... ) seems to be random in its behaviour. It is therefore useless. Do not use this!

    localize is the correct function to use. Example:

    localdatetime_aware = tz.localize(datetime_nonaware)
    

    Or a more complete example:

    import pytz
    from datetime import datetime
    pytz.timezone('Australia/Melbourne').localize(datetime.now())
    

    gives me a timezone aware datetime value of the current local time:

    datetime.datetime(2017, 11, 3, 7, 44, 51, 908574, tzinfo=<DstTzInfo 'Australia/Melbourne' AEDT+11:00:00 DST>)
    
    0 讨论(0)
提交回复
热议问题