Paul Ganssle <p.gans...@gmail.com> added the comment:

@Yi Luan

I think you may misunderstand what the `.timestamp()` function does - it 
returns an epoch time, which is the amount of time (in seconds) elapsed since 
the Unix epoch: https://en.wikipedia.org/wiki/Unix_time

The number is not different depending on your time zone:

    >>> from datetime import *
    >>> from dateutil import tz

    >>> dt = datetime(2019, 1, 1, tzinfo=timezone.utc)
    >>> print(f"{dt}: {dt.timestamp()}")
    2019-01-01 00:00:00+00:00: 1546300800.0

    >>> dt = dt.astimezone(tz.gettz("America/New_York"))
    >>> print(f"{dt}: {dt.timestamp()}")
    2018-12-31 19:00:00-05:00: 1546300800.0

    >>> dt = dt.astimezone(tz.gettz("Asia/Tokyo"))
    >>> print(f"{dt}: {dt.timestamp()}")
    2019-01-01 09:00:00+09:00: 1546300800.0

Note how the timestamp number is always the same.

Alexander's suggestion of using `datetime.now(tz=timezone.utc).timestamp()` is 
slightly misleading because `datetime.now().timestamp()` and 
`datetime.now(tz=timezone.utc).timestamp()` will always return the same value. 
I think he was just using that as shorthand for "replace datetime.utcnow() with 
datetime.now(tz=timezone.utc) in all cases".

When you have a naive datetime (with no tzinfo), the only options are to pick 
the time zone it represents and convert to UTC or to throw an error and say, 
"We don't know what time zone this represents, so we cannot do this operation." 
Python 2 used to throw an exception, but in Python 3 naive datetimes represent 
local times.

If you want "nominal number of seconds since 1970-01-01T00:00:00 *in this time 
zone*", you want something more like this:

  def seconds_since(dt, epoch=datetime(1970, 1, 1)):
    return (dt.replace(tzinfo=None) - epoch).total_seconds()

That does not take into account total elapsed time from DST transitions and the 
like - to do that, you'll want something more like this:

  def seconds_elapsed_since(dt, epoch=datetime(1970, 1, 1)):
    if epoch.tzinfo is None and dt.tzinfo is not None:
        epoch = epoch.replace(tzinfo=dt.tzinfo)
    return (dt - epoch).total_seconds()

I urge you not to do this in any sort of interop protocol, though, because 
integer timestamps are traditionally interpreted as Unix times, and if you 
start passing around an integer timestamp that represents "unix time plus or 
minus a few hours", you are likely to create bugs when someone mistakes it for 
a unix time.

----------

_______________________________________
Python tracker <rep...@bugs.python.org>
<https://bugs.python.org/issue39970>
_______________________________________
_______________________________________________
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com

Reply via email to