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
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 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
Ok, I need a way to get the timestamp for the current day but at a certain time.
So for example, I want the unix timestamp for today at 7:30PM - what would I do to get that value? In PHP it's possible with the strtotime() but I'm not sure how to do this in Python.
Edit: To clarify, I mean the current day not a statically written day. So if I ran this script tomorrow it would return the timestamp for 7:30PM tomorrow.
from datetime import datetime
now = datetime.utcnow() # Current time
then = datetime(1970,1,1) # 0 epoch time
ts = now - then
ts = ts.days * 24 * 3600 + ts.seconds
# alternatively, per Martijn Pieters
ts = int(ts.total_seconds())
you can use the time module :
from datetime import datetime
from time import mktime
# like said Ashoka
ts = datetime.strptime("2014-7-7 7:30","%Y-%m-%d %H:%M")
#you have now your datetime object
print mktime(ts.timetuple())
# print 1404711000.0
print int(mktime(ts.timetuple()))
# print 1404711000
be careful mktime don't care of time zone so if you want to have a UTC time zone and still use time , convert date before:
import pytz
fr = pytz.timezone('Europe/Paris')
#localize
ts = fr.localize(ts)
#timestamp in UTC
mktime(ts.astimezone(pytz.UTC).timetuple())
calendar.timegm method returns a timestamp out of passed time tuple:
import calendar
from datetime import datetime
d = datetime(year=2014, month=7, day=8, hour=7, minute=30)
calendar.timegm(d.utctimetuple())
# 1404804600
datetime.utcfromtimestamp(calendar.timegm(d.utctimetuple()))
# datetime.datetime(2014, 7, 8, 7, 30)
The important things are utctimetuple and utcfromtimestamp. You would certainly want a UTC timestamp, and not one in your local timezone.
import calendar
from datetime import datetime
from pytz import timezone, utc
tz = timezone('Europe/Warsaw')
aware = datetime(year=2014, month=7, day=8, hour=7, minute=30)
aware = tz.localize(aware)
# datetime.datetime(2014, 7, 8, 7, 30, tzinfo=<DstTzInfo 'Europe/Warsaw' CEST+2:00:00 DST>)
stamp = calendar.timegm(aware.utctimetuple())
# 1404797400
d = datetime.utcfromtimestamp(stamp)
# datetime.datetime(2014, 7, 8, 5, 30)
d = d.replace(tzinfo=utc)
d.astimezone(tz)
# datetime.datetime(2014, 7, 8, 7, 30, tzinfo=<DstTzInfo 'Europe/Warsaw' CEST+2:00:00 DST>)
I have a datetime that i get from a database, this datetime is a UTC datetime. But when i pull it from the DB, it is unaware of the timezone. What i need to do, is convert this datetime to a "seconds from epoch" time for another function. The problem with this, is that the system's time is in PST and i am not able to change it for specific reasons.
So, what i want to do is, take this datetime that i get from the database, and tell python that this datetime is a UTC datetime. Every way that i have done that, results in it losing time or gaining time due to timezone conversions. Again, not trying to convert the time, just trying to specify that it is UTC.
If anyone can help with this that would be great.
Thanks!
Example
Assume database_function() returns a datetime data type that is '2013-06-01 01:06:18'
datetime = database_function()
epoch = datetime.strftime('%s')
pytz.utc.localize(database_function()).datetime.strftime('%s')
datetime.replace(tzinfo=pytz.utc).datetime.strftime('%s')
Both of these return a epoch timestamp of 1370077578
But, it SHOULD return a timestamp of 1370048778 per http://www.epochconverter.com/
Remember, this timestamp is a utc timestamp
Using the fabolous pytz:
import datetime, pytz
dt = datetime.datetime(...)
utc_dt = pytz.utc.localize(dt)
This creates a tz-aware datetime object, in UTC.
How about Setting timezone in Python This appears to reset the timezone within your python script. You are changing the time zone that your system sees given the specified time, not changing the specified time into the specified time zone. You probably want to set it to 'UTC'
time.tzset()
Resets the time conversion rules used by the library routines.
The environment variable TZ specifies how this is done.
New in version 2.3.
Availability: Unix.
I do not have this available on my home platform so I could not test it. I had to get this from the previous answer.
The answer marked best on the question is:
>>> import os, time
>>> time.strftime('%X %x %Z')
'12:45:20 08/19/09 CDT'
>>> os.environ['TZ'] = 'Europe/London'
>>> time.tzset()
>>> time.strftime('%X %x %Z')
'18:45:39 08/19/09 BST'
To get the specific values you've listed:
>>> year = time.strftime('%Y')
>>> month = time.strftime('%m')
>>> day = time.strftime('%d')
>>> hour = time.strftime('%H')
>>> minute = time.strftime('%M')
See here for a complete list of directives. Keep in mind that the strftime() function will always return a string, not an integer or other type.
You can Use pytz, which is a time zone definitions package.
from datetime import datetime
from pytz import timezone
fmt = "%Y-%m-%d %H:%M:%S %Z%z"
# Current time in UTC
now_utc = datetime.now(timezone('UTC'))
print now_utc.strftime(fmt)
# Convert to US/Pacific time zone
now_pacific = now_utc.astimezone(timezone('US/Pacific'))
print now_pacific.strftime(fmt)
# Convert to Europe/Berlin time zone
now_berlin = now_pacific.astimezone(timezone('Europe/Berlin'))
print now_berlin.strftime(fmt)
output:
2014-04-04 21:50:55 UTC+0000
2014-04-04 14:50:55 PDT-0700
2014-04-04 23:50:55 CEST+0200
or may be it helps
>> import pytz
>>> import datetime
>>>
>>> now_utc = datetime.datetime.utcnow() #Our UTC naive time from DB,
for the time being here I'm taking it as current system UTC time..
>>> now_utc
datetime.datetime(2011, 5, 9, 6, 36, 39, 883479) # UTC time in Naive
form.
>>>
>>> local_tz = pytz.timezone('Europe/Paris') #Our Local timezone, to
which we want to convert the UTC time.
>>>
>>> now_utc = pytz.utc.localize(now_utc) #Add Timezone information to
UTC time.
>>>
>>> now_utc
datetime.datetime(2011, 5, 9, 6, 36, 39, 883479, tzinfo=<UTC>) # The
full datetime tuple
>>>
>>> local_time = now_utc.astimezone(local\_tz) # Convert to local
time.
>>>
>>> local_time #Current local time in Paris
datetime.datetime(2011, 5, 9, 8, 36, 39, 883479, tzinfo=<DstTzInfo
'Europe/Paris' CEST+2:00:00 DST>)
Here is one way, using the pytz module:
import pytz
utc_datetime = (datetime.datetime(1970, 1, 1, tzinfo=pytz.utc)
+ datetime.timedelta(seconds=seconds_since_epoch)
If you don't want to install the pytz module, you can copy the example UTC class from the datetime documentation (search for "class UTC"):
https://docs.python.org/2/library/datetime.html#tzinfo-objects
Here's stdlib only solution without 3-party modules.
.., this datetime is a UTC datetime. But when i pull it from the DB, it is unaware of the timezone. What i need to do, is convert this datetime to a "seconds from epoch" time for another function.emphasize is mine
To convert an unaware (naive) datetime object that represents time in UTC to POSIX timestamp:
from datetime import datetime
timestamp = (dt_from_db - datetime(1970, 1, 1)).total_seconds()
Example:
>>> from datetime import datetime
>>> dt = datetime.strptime('2013-06-01 01:06:18', '%Y-%m-%d %H:%M:%S')
>>> (dt - datetime(1970, 1, 1)).total_seconds()
1370048778.0
See Converting datetime.date to UTC timestamp in Python that provides solutions for various Python versions.
To answer the question from the title: In general you need pytz library to handle timezones in Python. In particular, you should use .localize method to convert an unaware datetime object into timezone-aware one.
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal
tz = get_localzone() # local timezone whatever it is (just an example)
aware_dt = tz.localize(naive_dt_in_local_timezone, is_dst=None)
is_dst=None asserts that naive_dt_in_local_timezone exists and unambiguous.
Though you don't need it for UTC timezone because it always has the same UTC offset (zero) around the year and in all past years:
import pytz
aware_dt = utc_dt.replace(tzinfo=pytz.utc)
See Python - simplest and most coherent way to get timezone-aware current time in UTC? (it provides a stdlib-only solution):
aware_dt = utc_dt.replace(tzinfo=timezone.utc)
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)