Python datetime utcnow vs Luxon Datetime.fromMillis? - python

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 ?

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.

Related

Timestamp to non UTC Datetime object is substracting hours twice

I have the following timestamp 1550588656 which translates to 2019-02-19 15:04:16+00:00 in UTC time convention.
I want to convert it to my country's time convention (UTC or GMT -3 in this time of the year) so it should translate to 2019-02-19 12:04:16+00:00
I have read on other SO questions that first I have to convert the timestamp to an UTC aware Datetime object and then localize it, I'm doing it like this
# string format time
naive_datetime = datetime.fromtimestamp(timestamp).strftime('%Y-%m-%d %H:%M:%S')
# string parse time
naive_datetime = datetime.strptime(naive_datetime, "%Y-%m-%d %H:%M:%S")
# make naive Datetime object UTC aware
utc_datetime = naive_datetime.replace(tzinfo=pytz.UTC)
So now it's not a naive Datetime object, from here I should be able to localize it to my country's timezone. In Python that is pytz.timezone('America/Santiago')
So it should go something like this
cltime = pytz.timezone('America/Santiago')
local_datetime = utc_datetime.astimezone(cltime)
But I'm getting 2019-02-19 09:04:16-03:00 (UTC or GTM -6 ) as a result and I don't know why.
Can someone explain? My intuition tells me it's probably a simple thing I'm not looking at, but I've spent some minutes in it and I haven't been able to tell yet.
If you look at the documentation for fromtimestamp:
Return the local date and time corresponding to the POSIX timestamp
So the problem is that it is already doing a conversion from UTC to the local time, and you're doing it a second time.
First of all you have epoc time (UTC timestamp). You need to convert it into datetime object (native) which is followed by converting native time to aware time and than finally convert it to your local time.
Convert your timestamp to native datetime object
native_datetime = datetime.fromtimestamp(1550588656)
convert native datetime object to aware time (add timezone info, will add timezone info to native timezone UTC for current)
import pytz
utc_time = native_datetime.replace(tzinfo=pytz.timezone("UTC"))
localising aware datetime to your local datetime
local_time = utc_time.astimezone(pytz.timezone("America/Santiago"))
You can replace "America/Santiago" with your local time zone
I think this would help you to solve your problem. Thanks!

fromtimestamp returns different results

I have the following code:
import datetime
dt = 1546955400
print(datetime.datetime.fromtimestamp(dt))
When I run this code on my local machine, I get the correct (expected) time which is
2019-01-08 15:50:00.
However I tried running this exact same code on a VM and the result was
2019-01-08 13:50:00 (two hours earlier). Why is this is happening and how can I fix it so that I always get the first one regardless of where the code is running?
datetime.datetime.fromtimestamp() returns local time. From the documentation:
Return the local date and time corresponding to the POSIX timestamp, such as is returned by time.time(). If optional argument tz is None or not specified, the timestamp is converted to the platform’s local date and time, and the returned datetime object is naive.
The timestamp value is an offset in seconds from the UNIX epoch value, midnight 1 January 1970, in the UTC timezone. The local time is a system-wide configured offset from UTC, the local timezone.
If your VM is producing unexpected results, you need to configure the timezone of the OS.
Alternatively, ignore timezones and only deal with time in the UTC timezone. For timestamps, that means using the datetime.datetime.utcfromtimestamp() function.
Your specific timestamp is 13:50 UTC:
>>> dt = 1546955400
>>> from datetime import datetime
>>> datetime.utcfromtimestamp(dt)
datetime.datetime(2019, 1, 8, 13, 50)
>>> print(_)
2019-01-08 13:50:00
so your VM is either set to the UTC or the GMT timezone (the latter is currently at UTC+0, until the switch to the UK daylight saving timezone BST). Your local system is in a UTC+2 timezone, given your stated location from your profile that'd be EEE, Easter European Time.
Another option is to create a timezone-aware timestamp by passing in a tz argument. If you have a specific UTC offset, just create a datetime.timezone() instance for that offset:
utcplus2 = datetime.timezone(datetime.timedelta(hours=2))
datetime.datetime.fromtimestamp(dt, utcplus2)
However, it is usually better to store and operate on UTC datetime instances everywhere, and only convert to specific timezones when displaying information to users. This simplifies datetime handling as it lets you avoid a number of timezone corner cases and problems, such as mixing datetime information from different timezones and timezones with a summer and winter time distinction.

Datetime returns wrong time in unix

I have a wired situation here with returning the time in unix format.
I have this function:
def get_today_date():
nowDate = str(datetime.datetime.utcnow().date())
unix_date = time.mktime(datetime.datetime.strptime(nowDate, "%Y-%m-%d").timetuple())
return (unix_date)
it's straightforward when I print the value of "nowDate" -> it gives me the right value I want (ex: 7/29/2018 00:00:00 UTC) which is correct. But when I change the format from Unix timestamp to date format and get only the date without time, It gives me (7/28/2018).
I've took the value in unix and checked it, it gives me (7/28/2018 21:00:00). Why?
My laptop is in a UTC +3 timezone.
Did something go wrong in the conversion? Or its an internal error in my laptop makes the output wrong?
If you're looking for today's date/time, use datetime.datetime.now(), if you need just the date, use datetime.datetime.today() it's automatically converted into your timezone.
If you play with UTC-based functions, you'll get 3 hours offset for your location, which sometimes might result in time being 21:00 of previous day instead of midnight of the next one -- that's quite reasonable =)
you may use the following approach:
utcnow = datetime.datetime.utcnow()
midnight = time.mktime( datetime.datetime( utcnow.year, utcnow.month, utcnow.day).timetuple() )

Timestamp with utc and any other timezone is coming out to be same with arrow

import arrow
print arrow.utcnow()
print arrow.utcnow().timestamp
print arrow.utcnow().to('Asia/Kolkata')
print arrow.utcnow().to('Asia/Kolkata').timestamp
I need the timestamp (in int) of 'Asia/Kolkata' timezone, which is +5:30 from utc.
arrow.utcnow() and arrow.utcnow().to('Asia/Kolkata') are coming out to be different and the second one is +5:30 the first, as expected.
However, arrow.utcnow().timestamp and arrow.utcnow().to('Asia/Kolkata').timestamp are still coming out to be same.
I am sure I am missing something very basic here, but can anyone explain this?
I think "timestamp", by definition, is always in UTC:
The Unix time (or Unix epoch or POSIX time or Unix timestamp) is a
system for describing points in time, defined as the number of seconds
elapsed since midnight proleptic Coordinated Universal Time (UTC) of
January 1, 1970, not counting leap seconds.
If you take your localized time string, convert it to a UTC date time (that is, 5pm Kolkata time becomes 5pm UTC), then you can get a timestamp that corresponds to the local clock time. Example:
import arrow
print arrow.utcnow()
print arrow.utcnow().timestamp
kolkata = arrow.utcnow().to('Asia/Kolkata')
print kolkata.replace(tzinfo='UTC').timestamp
Timestamps are UTC, this is also described in the Arrow docs
timestamp
Returns a timestamp representation of the Arrow object, in
UTC time.
Arrow will let you convert a non-UTC timestamp into arrow time but it won't let you shoot yourself in the foot by generating non-UTC timestamps for you.
classmethod fromtimestamp(timestamp, tzinfo=None)
Constructs an Arrow
object from a timestamp, converted to the given timezone.
Parameters: timestamp – an int or float timestamp, or a str that
converts to either. tzinfo – (optional) a tzinfo object. Defaults to
local time. Timestamps should always be UTC. If you have a non-UTC
timestamp:
arrow.Arrow.utcfromtimestamp(1367900664).replace(tzinfo='US/Pacific')
<Arrow [2013-05-07T04:24:24-07:00]>
The full docs are here:
http://arrow.readthedocs.io/en/latest/

Python pytz: convert local time to utc. Localize doesn't seem to convert

I have a database that stores datetime as UTC. I need to look up info from a particular time, but the date and time are given in a local time, let's say 'Europe/Copenhagen'. I'm given these as:
year = 2012; month = 12; day = 2; hour = 13; min = 1;
So, I need to convert these to UTC so I can look them up in the database. I want to do this using pytz. I am looking at localize:
local_tz = timezone('Europe/Copenhagen')
t = local_tz.localize(datetime.datetime(year, month, day, hour, min))
But I'm confused about localize(). Is this assuming that year, etc, are given to me in local time? Or, is it assuming that they they are given in UTC and now it has converted them to local time?
print t gives me:
2012-12-02 13:01:00+01:00
So it seems that it assumed that the original year, etc was in utc; hours is now 13+1 instead of 13. So what should I do instead? I have read the pytz documentation and this does not make it clearer to me. It mentions a lot that things are tricky so I'm not sure whether pytz is actually solving these issues. And, I don't always know if the examples are showing me things that work or things that won't work.
I tried normalize:
print local_tz.normalize(t)
That gives me the same result as print t.
EDIT: With the numbers given above for year etc. it should match up with information in the database for 2012-12-2 12:01. (since Copenhagen is utc+1 on that date)
localize() attaches the timezone to a naive datetime.datetime instance in the local timezone.
If you have datetime values in a local timezone, localize to that timezone, then use .astimezone() to cast the value to UTC:
>>> localdt = local_tz.localize(datetime.datetime(year, month, day, hour, min))
>>> localdt.astimezone(pytz.UTC)
datetime.datetime(2012, 12, 2, 12, 1, tzinfo=<UTC>)
Note that you don't need to do this, datetime objects with a timezone can be compared; they'll both be normalized to UTC for the test:
>>> localdt.astimezone(pytz.UTC) == localdt
True
If you know the incoming time representation is in the Europe/Copenhagen timezone, you can create it as timezone-aware to begin with:
local_tz = timezone('Europe/Copenhagen')
t = local_tz.localize(datetime.datetime(year, month, day, hour, min))
You can then "convert" this to UTC with:
t_utc = t.astimezone(pytz.UTC)
but this might not be necessary, depending on how sane your database drivers are. t and t_utc represent the same point-in-time and well-behaving code should treat them interchangeably. The (year, month, day, hour, minute, second, …) tuple is merely a human-readable representation of this point-in-time in a specific time zone and calendar system.

Categories

Resources