I am trying to convert a Unix timestamp to AoE time. I tried pytz but it seems that there is no AoE time in pytz. Is there any way that I can do it?
tz = pytz.timezone('AOE')
timestamp_aoe = datetime.fromtimestamp(timestamp, tz).isoformat()
The AoE timezone (Anywhere on Earth; UTC-12) is not defined in the IANA tz database as far as I can tell. It's a time zone with static UTC offset of -12 h, you can also find it under "yankee" or "NATO" time, see military time zones.
Since the UTC offset never changed in the past (no DST etc.), you can simply define it by yourself:
from datetime import datetime, timezone, timedelta
timestamp = 1582013600.5 # example UNIX time
tz = timezone(timedelta(hours=-12), name='AOE')
dt_aoe = datetime.fromtimestamp(timestamp, tz)
print(repr(dt_aoe), dt_aoe.isoformat())
# datetime.datetime(2020, 2, 17, 20, 13, 20, 500000, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=43200), 'AOE'))
# 2020-02-17T20:13:20.500000-12:00
Related
In my program, I need to use a datetime object that is in utc time not my local time, and I also need the timestamp (seconds since epoch) of that datetime object.
import datetime
my_time = datetime.datetime.utcnow()
timestamp = my_time.timestamp()
However, the timestamp was wrong. It was the timestamp when my local time is my_time, not the correct timestamp when the utc time is my_time. How can I get the correct timestamp? I don't want to create another datetime object because there might be microseconds of difference.
Edit
Example:
import datetime
utc_time = datetime.datetime.utcnow()
local_time = datetime.datetime.now()
utc_timestamp = utc_time.timestamp()
local_timestamp = local_time.timestamp()
print(utc_timestamp)
print(local_timestamp)
My result:
1633133103.945903
1633161903.945903
The two are different by 8 hours, because I live in UTC+08:00 time zone, and the first one is not "seconds since epoch". I want to get the correct timestamp from utc_time because technically those two object were not created at the same time.
use aware datetime,
from datetime import datetime, timezone
t_loc = datetime.now().astimezone() # local time, as set in my OS (tz Europe/Berlin)
t_utc = datetime.now(timezone.utc)
print(repr(t_loc))
print(repr(t_utc))
# e.g.
# datetime.datetime(2021, 10, 2, 11, 10, 26, 920792, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200), 'CEST'))
# datetime.datetime(2021, 10, 2, 9, 10, 26, 920809, tzinfo=datetime.timezone.utc)
This will give you correct Unix time as well:
t_loc_unix = t_loc.timestamp()
t_utc_unix = t_utc.timestamp()
print(t_loc_unix, t_utc_unix)
# 1633165826.920792 1633165826.920809
Unix timestamps are now equal as it should be since Unix time always (should) refers to UTC.
I have a problem converting timestamp to GMT. As far as I know, the timestamp is allways in GMT time so I expect datetime.fromtimestamp returning GMT or timezone-aware datetime but it returns my local (Bratislava/Prague) datetime.
import datetime
datetime.datetime.fromtimestamp(1566720000)
datetime.datetime(2019, 8, 25, 10, 0)
But according to Epoch Converter it is
GMT: Sunday, August 25, 2019 8:00:00 AM
EDIT: datetime.datetime.fromtimestamp(1566720000).tzinfo returns nothing so it is not tz aware.
Do you know where is the problem?
fromtimestamp() returns the local date and time. If it needs to be tz-aware, the parameter tz must be specified:
https://docs.python.org/3/library/datetime.html#datetime.datetime.fromtimestamp
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.
If you need the a datetime object in UTC, use utcfromtimestamp instead:
datetime.utcfromtimestamp(timestamp)
Looks like you want utcfromtimestamp
>>> datetime.datetime.utcfromtimestamp(1566720000)
datetime.datetime(2019, 8, 25, 8, 0)
Keep in mind this still returns a naive datetime object
It is not a good idea to use datetime.datetime.utcfromtimestamp(). It returns a naive datetime object (without time zone information) which would be interpreted by many functions as datetime in your local time zone! It is much better to use time zone aware objects.
The following code returns time zone aware datetime in the UTC time zone.
>>> import datetime
>>> datetime.datetime.fromtimestamp(1566720000, datetime.timezone.utc)
datetime.datetime(2019, 8, 25, 8, 0, tzinfo=datetime.timezone.utc)
I am trying to convert unix time on my local system to UTC time in unix format, but after converting it the final time is going off by +1 hour.
To do so, I wrote the following code.
from dateutil import tz
import time
from time
import mktime
now_time = time.time()
print('current local unix time', now_time)
print(time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(now_time)))
to_zone = tz.tzutc()
from_zone = tz.tzlocal()
t = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(now_time))
utc = datetime.strptime(str(t), '%Y-%m-%d %H:%M:%S')
utc = utc.replace(tzinfo=from_zone)
central = utc.astimezone(to_zone)
print('Converted to UTC ',central)
unix_secs = mktime(central.timetuple())
print('Central unix time ',unix_secs)
print('central unix time to dattime ', time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(unix_secs)))
The output is as follows
current local unix time 1563985835.3707478
2019-07-24 12:30:35
Converted to UTC 2019-07-24 16:30:35+00:00
Central unix time 1564003835.0
central unix time to dattime 2019-07-24 17:30:35
can someone please tell me what am I doing wrong here and how can I fix this?
I guess you're incorrectly transform datetimes with TZ information when converting the timestamp to datetime instance using time.strftime and after that datetime.strptime or when using mktime.
Anyway, there is much easier way to achieve what you want:
from datetime import datetime, timezone
# Get current timestamp
now_timestamp = time.time()
>> 1563987839.054703
# Get datetime of that timestamp but already in UTC.
# This preserves TZ information and allows
# to correctly do transition to the timestamp again.
utc_time = datetime.utcfromtimestamp(now_timestamp)
>> datetime.datetime(2019, 7, 24, 17, 3, 59, 54703)
# Convert UTC datetime back to timestamp
utc_timestamp = utc_time.timestamp()
>> 1563977039.054703
# Verify that this timestamp is indeed UTC
# I am in UTC+3 timezone now
datetime.now()
>> datetime.datetime(2019, 7, 24, 20, 4, 10, 500229)
datetime.fromtimestamp(utc_timestamp)
>> datetime.datetime(2019, 7, 24, 17, 3, 59, 54703)
A Unix timestamp is always in UTC.
It is "the number of seconds that have elapsed since 00:00:00 Thursday, 1 January 1970, UTC".
In other words, it's the duration. It doesn't matter in the slightest where you do this calculation. Subtraction works the same everywhere in the universe. Durations have absolutely nothing to do with timezones.
Reference - https://en.wikipedia.org/wiki/Unix_time
This should be very simple, but I can't quite figure it out in Python.
I want to have a function which takes two arguments, a UTC time in seconds and a zoneinfo name like 'Europe/Vienna' and returns the offset in seconds from local time and UTC for that point in time.
In C it would be:
/* ... code to to set local time to the time zone I want to compare against,
not shown here. Then call function below to get difference vs localtime.
Hardly an ideal solution,
but just to demonstrate what I want in a "lingua franca" (C): */
int get_diff_vs_localtime(const time_t original_utc_time)
{
struct tm* ts;
ts = localtime(&original_utc_time);
return mktime(ts) - original_utc_time;
}
I guess my question really boils down to: "given an Olson timezone (example 'Europe/Stockholm') and a UTC time, what is the local time?
Assuming "UTC time in seconds" means POSIX timestamp. To convert it to Stockholm time:
from datetime import datetime
import pytz
tz = pytz.timezone('Europe/Stockholm')
utc_dt = datetime.utcfromtimestamp(posix_timestamp).replace(tzinfo=pytz.utc)
dt = tz.normalize(utc_dt.astimezone(tz))
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
tz.normalize() is unnecessary if the source timezone is UTC (like in this case).
A simpler alternative is to use fromtimestamp()'s tz parameter, to convert "seconds since the epoch" to local time:
from datetime import datetime
import pytz
tz = pytz.timezone('Europe/Stockholm')
dt = datetime.fromtimestamp(posix_timestamp, tz)
print(dt.strftime('%Y-%m-%d %H:%M:%S %Z%z'))
Both examples produce the same result.
If local machine uses "right" timezones then to convert POSIX timestamp received from an external source to UTC, an explicit formula could be used:
from datetime import datetime, timedelta
import pytz
utc_dt = datetime(1970, 1, 1, tzinfo=pytz.utc) + timedelta(seconds=posix_timestamp)
The latest formula may also support a larger date range (less likely issues with dates before 1970, after 2038 or 3000 years).
If the timestamp comes from the local "right" source then the first two examples should be used instead (they call "right" time.gmtime()).
You could use pytz and datetime to do something in the manner of:
from datetime import datetime
from pytz import timezone
def get_diff(now, tzname):
tz = timezone(tzname)
utc = timezone('UTC')
utc.localize(datetime.now())
delta = utc.localize(now) - tz.localize(now)
return delta
Which for the following example...
now = datetime.utcnow()
print(now)
tzname = 'Europe/Stockholm'
delta = get_diff(now, tzname)
print(delta)
now_in_stockholm = now + delta
print(now_in_stockholm)
... outputs:
2012-10-02 14:38:56.547475
2:00:00
2012-10-02 16:38:56.547475
This is pretty old, but I couldn't find a great answer, so here's what I came up with:
from datetime import datetime
local = datetime.now()
utc = datetime.utcnow()
int((local - utc).days * 86400 + round((local - utc).seconds, -1))
Returns:
-21600
because I am (currently) 21600 seconds (6 hours) behind UTC.
Note: the second date calculated (in this case UTC) needs to be rounded since there is a super small difference in time at each calculation.
I guess my question really boils down to: "given an Olson timezone
(example 'Europe/Stockholm') and a UTC time, what is the local time?
If I understand your problem correctly:
from pytz import timezone
import datetime, time
tz = timezone('Asia/Kuwait')
utc_dt = datetime.datetime.utcfromtimestamp(time.time())
utc_dt + tz.utcoffset(utc_dt)
>>> tz.utcoffset(utc_dt).seconds
10800
>>> tz
<DstTzInfo 'Asia/Kuwait' LMT+3:12:00 STD>
>>> utc_dt + tz.utcoffset(utc_dt)
datetime.datetime(2012, 10, 2, 17, 13, 53, 504322)
>>> utc_dt
datetime.datetime(2012, 10, 2, 14, 13, 53, 504322)
I am writing a program which deals a lot with timezones and crossing them. The two things I deal with most are creating a datetime object from "now" and then localizing a naive datetime object.
To create a datetime object from now in the pacific timezone, I am currently doing this (python 2.7.2+)
from datetime import datetime
import pytz
la = pytz.timezone("America/Los_Angeles")
now = datetime.now(la)
Is this correct with regards to DST? If not, I suppose I should be doing:
now2 = la.localize(datetime.now())
My question is why? Can anyone show me a case where the first is wrong and the seconds is right?
As for my seconds question, suppose I had a naive date and time from some user input for 9/1/2012 at 8:00am in Los Angeles, CA. Is the right way to make the datetime like this:
la.localize(datetime(2012, 9, 1, 8, 0))
If not, how should I be building these datetimes?
From the pytz documentation:
The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans.
So ideally you should be using utcnow instead of now.
Assuming for some reason that your hands are tied and you need to work with local times, you can still run into a problem with trying to localize the current time if you're doing it during the daylight saving transition window. The same datetime might occur twice, once during daylight time and again during standard time, and the localize method doesn't know how to settle the conflict unless you tell it explicitly with the is_dst parameter.
So to get the current UTC time:
utc = pytz.timezone('UTC')
now = utc.localize(datetime.datetime.utcnow())
And to convert it to your local time (but only when you must):
la = pytz.timezone('America/Los_Angeles')
local_time = now.astimezone(la)
Edit: as pointed out in the comments by #J.F. Sebastian, your first example using datetime.now(tz) will work in all cases. Your second example fails during the fall transition as I outlined above. I still advocate using UTC instead of local time for everything except display.
The first solution is correct with regards to DST, and the second solution is bad.
I'll give an example. Here in Europe, when running this code:
from datetime import datetime
import pytz # $ pip install pytz
la = pytz.timezone("America/Los_Angeles")
fmt = '%Y-%m-%d %H:%M:%S %Z%z'
now = datetime.now(la)
now2 = la.localize(datetime.now())
now3 = datetime.now()
print(now.strftime(fmt))
print(now2.strftime(fmt))
print(now3.strftime(fmt))
I get the following:
2012-08-30 12:34:06 PDT-0700
2012-08-30 21:34:06 PDT-0700
2012-08-30 21:34:06
datetime.now(la) creates a datetime with the current time in LA, plus the timezone information for LA.
la.localize(datetime.now()) adds timezone information to the naive datetime, but does no timezone conversion; it just assumes the time was already in this timezone.
datetime.now() creates a naive datetime (without timezone information) with the local time.
As long as you are in LA, you will not see the difference, but if your code ever runs somewhere else, it will probably not do what you wanted.
Apart from that, if you ever need to deal seriously with timezones, it is better to have all your times in UTC, saving yourself a lot of trouble with DST.
This works:
# naive datetime
d = datetime.datetime(2016, 11, 5, 16, 43, 45)
utc = pytz.UTC # UTC timezone
pst = pytz.timezone('America/Los_Angeles') # LA timezone
# Convert to UTC timezone aware datetime
d = utc.localize(d)
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>)
# show as in LA time zone (not converting here)
d.astimezone(pst)
>>> datetime.datetime(2016, 11, 5, 9, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# we get Pacific Daylight Time: PDT
# add 1 day to UTC date
d = d + datetime.timedelta(days=1)
>>> datetime.datetime(2016, 11, 6, 16, 43, 45, tzinfo=<UTC>)
d.astimezone(pst) # now cast to LA time zone
>>> datetime.datetime(2016, 11, 6, 8, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>)
# Daylight saving is applied -> we get Pacific Standard Time PST
This DOES NOT work:
# naive datetime
d = datetime.datetime(2016, 11, 5, 16, 43, 45)
utc = pytz.UTC # UTC timezone
pst = pytz.timezone('America/Los_Angeles') # LA timezone
# convert to UTC timezone aware datetime
d = utc.localize(d)
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>)
# convert to 'America/Los_Angeles' timezone: DON'T DO THIS
d = d.astimezone(pst)
>>> datetime.datetime(2016, 11, 5, 9, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# we are in Pacific Daylight Time PDT
# add 1 day to LA local date: DON'T DO THAT
d = d + datetime.timedelta(days=1)
>>> datetime.datetime(2016, 11, 6, 9, 43, 45,
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>)
# Daylight Saving is NOT respected, we are still in PDT time, not PST
Conclusion:
datetime.timedelta() DOES NOT account for daylight saving.
Do your time add/subtract in UTC timezone ALWAYS.
Cast to local time only for output / display.
The pytz website says:
Unfortunately using the tzinfo argument of the standard datetime
constructors ‘’does not work’’ with pytz for many timezones.
So you should not use datetime.now(la). I don't know the specifics, but some timezones operate on more exotic rules then we are used to, and python's datetime code can't handle them. By using pytz's code, they should be handled correctly since that's pytz's purpose. It may also have issues for the times that occur twice thanks to jumping times in daylight savings.
As for the second question, that's exactly what the documentation shows, so you should be good.