Time zone field in isoformat

后端 未结 3 1361
死守一世寂寞
死守一世寂寞 2020-11-29 07:23

I have a timestamp that is supposed to be in EST:

2014-10-06T18:06:40-04:56

I understand this first part: 2014-10-06T18:06:40,

3条回答
  •  再見小時候
    2020-11-29 08:17

    What does -04:56 mean here?`

    It means that the code that generates the input timestamp is broken in such a way that demonstrates the lack of understanding of how pytz timezones work. You should not trust its results, if you think that only the UTC offset (-04:56) is wrong but the date itself is the correct time in Eastern Time Zone then to parse the time, do:

    #!/usr/bin/env python
    from datetime import datetime, timedelta
    import pytz
    
    tz = pytz.timezone('America/New_York')
    
    naive = datetime.strptime("2014-10-06T18:06:40-04:56"[:-6],
                              "%Y-%m-%dT%H:%M:%S")
    start_time = tz.localize(naive, is_dst=None)
    end_time = tz.normalize(start_time + timedelta(seconds=400))
    print(start_time.isoformat())
    print(end_time.isoformat())
    
    • you should use tz.localize() instead of assigning tzinfo attribute directly
    • is_dst=None asserts that the input time exists and it is unambiguous
    • tz.normalize() is necessary if date arithmetics crosses DST boundaries

    Output

    2014-10-06T18:06:40-04:00
    2014-10-06T18:13:20-04:00
    

    Why you need localize(), normalize() is described in the pytz docs (the part about localize()/normalize() is the very first note in the documentation).

    Why -04:56 UTC offset is wrong in 2014 in Eastern Time Zone

    UTC offset in the same place may be different at different times due to DST transitions or other reasons (such as war or because some politician thinks it is a good idea) e.g., here's possible values for US/Eastern:

    >>> import pytz
    >>> pytz.timezone('US/Eastern')
    {(datetime.timedelta(-1, 72000),
      datetime.timedelta(0, 3600),
      'EWT'): ,
     (datetime.timedelta(-1, 68640),
      datetime.timedelta(0),
      'LMT'): ,
     (datetime.timedelta(-1, 72000),
      datetime.timedelta(0, 3600),
      'EDT'): ,
     (datetime.timedelta(-1, 68400),
      datetime.timedelta(0),
      'EST'): ,
     (datetime.timedelta(-1, 72000),
      datetime.timedelta(0, 3600),
      'EPT'): }
    

    Notice the UTC offset for LMT tzinfo: timedelta(-1, 68640) == '-4:56:00'. The way to get it is to use the incorrect code:

    #XXX BROKEN, DO NOT DO IT
    >>> dt = datetime(2014, 10, 6, tzinfo=pytz.timezone('US/Eastern'))
    >>> dt
    datetime.datetime(2014, 10, 6, 0, 0, tzinfo=)
    >>> dt.isoformat()
    2014-10-06T00:00:00-04:56
    

    Assigning tzinfo directly doesn't allow pytz to choose the correct tzinfo for the given time and some random tzinfo object among available is used instead. You should always use tz.localize() to attach the correct timezone info.

提交回复
热议问题