Search code examples
pythondatetimetimezoneluxon

Python datetime utcnow vs Luxon Datetime.fromMillis?


I'm trying to wrap my head in understanding the implication of using .utcnow vs. .now on Python's DateTime.

Here's the reason for my confusion: I live in France. Right now, we have a +1 hour on the UTC timezone (CET timezone in winter (now) / CEST (+2) timezone in summer).

If I take the following value :

dt = datetime.datetime.utcnow()
dt.strftime('%c') # Thu Dec  9 16:17:38 2021
int(dt.timestamp()) # 1639063064

This is correct as it is, in France right now, 17h17. So, from my understanding, that timestamp, 1639063064, is the UTC representation of the time since EPOCH.

But if I test this value in the website Epoch Converter, I get

  • GMT: Thursday 9 December 2021 15:17:44
  • Your time zone: jeudi 9 décembre 2021 16:17:44 GMT+01:00

It seems that the website ALSO subtracts my timezone to an already "substracted" value, ending in removing twice the timezone and causing an invalid value.

The actual confusion is when I tried to import that UTC timestamp to Luxon on my front app, doing the following doesn't work :

DateTime.fromMillis(parseInt(ts), { zone: 'utc' }).toLocal().setLocale('en')

I'm one hour behind.

How can I "tell" Luxon that the current TS is in the UTC timezone, and calling toLocal will apply the proper user's timezone ?


Solution

  • It seems that the website ALSO substract my timezone t

    No, epochconverter.com isn't doing anything. The value 1639063064 really does represent 2021-12-09T15:17:44Z. That's not the value you want.

    I'm no Python expert, but I believe the problem is the combination of this utcnow() behavior (emphasis mine):

    Return the current UTC date and time, with tzinfo None.

    This is like now(), but returns the current UTC date and time, as a naive datetime object.

    And this timestamp() behavior:

    Naive datetime instances are assumed to represent local time and this method relies on the platform C mktime() function to perform the conversion.

    It sounds like you want to follow this advice:

    An aware current UTC datetime can be obtained by calling datetime.now(timezone.utc).

    So just change your first line to:

    dt = datetime.now(timezone.utc)
    

    ... and it should be okay.