I have a Cocoa timestamp (zero time of January 1st, 2001 00:00:00 UTC) that I need to convert in Python. When I use the following code it assumes a Unix timestamp input. Besides adding 31 years in seconds (Just under a billion seconds...) what's the best way to convert the time?
import datetime
print(datetime.datetime.fromtimestamp(int("495759456")).strftime('%Y-%m-%d %H:%M:%S'))
The output for this line of code is '1985-09-16 16:12:03'
Would something like this work for you:
from datetime import datetime
unix = datetime(1970, 1, 1) # UTC
cocoa = datetime(2001, 1, 1) # UTC
delta = cocoa - unix # timedelta instance
timestamp = datetime.fromtimestamp(int("495759456")) + delta
print(timestamp.strftime('%Y-%m-%d %H:%M:%S'))
I didn't specify timezone information for the two starts of time as they're in the same zone so I assume it shouldn't matter which is used when computing the difference. For converting the timestamp string, you may need to adjust for your timezone if it's different than the one in which the string was generated.
The above code produces 2016-09-16 15:57:36
One thing to be careful on when doing the conversion with the above solution, is to make sure that the Cocoa timestamp's unit is the same as the one you'd want in the unix timestamp. I've noticed that at many instance the cocoa timestamp is stored in nano seconds.
Unless you want your Unix timestamp to also be represented as nano seconds, make sure to do divide the cocoa timestamp by the appropriate number before conversion. e.g. Divide by 1000000000 to convert nano seconds to seconds etc...
Source
Related
I converted a UNIX timestamp to a human format (sorry I do not know the exact name of it) in a specific timezone (Africa/Algeria) and it evaluated to this: 2020-06-05 19:45:21+01:00. I looked into the datetime module documentation and from what I understood the +01:00, it is the +/-HH:MM offset from the UTC.
What I do not understand is why it is returned with the datetime object given it is already converted to the indicated timezone?
Could someone explain it to me?
Thanks.
POSIX timestamps (Unix time) represent time in seconds since the epoch, 1970-01-01 UTC. No time zone issues involved here. datetime objects on the other hand can be naive (not contain any time zone information) or time zone aware. What you have is a time zone aware datetime object - its string representation prints out as "2020-06-05 19:45:21+01:00". If it had been naive, it would only print "2020-06-05 19:45:21". The repr should also show you a specific time zone, e.g.
print(repr(dt_obj))
>>> datetime.datetime(2020, 6, 5, 19, 45, 21, tzinfo=tzfile('Africa/Algiers'))
The important point is that 2020-06-05 19:45:21+01:00 can be converted back to POSIX timestamp without ambiguity:
from datetime import datetime
datetime.fromisoformat("2020-06-05 19:45:21+01:00").timestamp()
# 1591382721.0
If it wasn't for the +01:00 (no tzinfo), Python would assume that the datetime object belongs in local time, i.e. OS setting; meaning that machines in different time zones would get a different timestamp. I'm on UTC+2, so I would get:
datetime.fromisoformat("2020-06-05 19:45:21").timestamp()
# 1591379121.0
which gives the same timestamp as
datetime.fromisoformat("2020-06-05 19:45:21+02:00").timestamp()
# 1591379121.0
The difference is that with the "+02:00" (tzinfo defined), it is obvious what is happening.
Pretty sure it's an easy one but I don't get it.
My local TZ is currently GMT+3, and when I take timestamp from datetime.utcnow().timestamp() it is indeed giving me 3 hours less than datetime.now().timestamp()
During another process in my flow, I take that utc timestamp and need to turn it into datetime.
When I'm doing fromtimestamp I get the right utc hour, but when I'm using utcfromtimestamp I get another 3 hours offset.
The documentation, though, asks me to use fromtimestamp for local timezone, and utcfromtimestamp for utc usages.
What am I missing ? is the initial assumption for both funcs is that the timestamp is given in local timezone ?
Thank you :)
The key thing to notice when working with datetime objects and their POSIX timestamps (Unix time) at the same time is that naive datetime objects (the ones without time zone information) are assumed by Python to refer to local time (OS setting). In contrast, a POSIX timestamp (should) always refer to seconds since the epoch UTC. You can unambiguously obtain that e.g. from time.time(). In your example, not-so-obvious things happen:
datetime.now().timestamp() - now() gives you a naive datetime object that resembles local time. If you call for the timestamp(), Python converts the datetime to UTC and calculates the timestamp for that.
datetime.utcnow().timestamp() - utcnow() gives you a naive datetime object that resembles UTC. However, if you call timestamp(), Python assumes (since naive) that the datetime is local time - and converts to UTC again before calculating the timestamp! The resulting timestamp is therefore off from UTC by twice your local time's UTC offset.
A code example. Let's make some timestamps. Note that I'm on UTC+2 (CEST), so offset is -7200 s.
import time
from datetime import datetime, timezone
ts_ref = time.time() # reference POSIX timestamp
ts_utcnow = datetime.utcnow().timestamp() # dt obj UTC but naive - so also assumed local
ts_now = datetime.now().timestamp() # dt obj naive, assumed local
ts_loc_utc = datetime.now(tz=timezone.utc).timestamp() # dt obj localized to UTC
print(int(ts_utcnow - ts_ref))
# -7200 # -> ts_utcnow doesn't refer to UTC!
print(int(ts_now - ts_ref))
# 0 # -> correct
print(int(ts_loc_utc - ts_ref))
# 0 # -> correct
I hope this clarifies that if you call datetime.utcfromtimestamp(ts_utcnow), you get double the local time's UTC offset. Python assumes (which I think is pretty sane) that the timestamp refers to UTC - which in fact, it does not.
My suggestion would be to use timezone-aware datetime objects; like datetime.now(tz=timezone.utc). If you're working with time zones, the dateutil library or Python 3.9's zoneinfo module are very helpful. And if you want to dig deep, have a look at the datetime src code.
I'm trying to collect real-time data with hdf5, but it doesn't support datetime for now, so I thought np.float64(timestamp) would be a better option than simple strings, from the standpoint of storage efficiency(8bits vs more than 8 bits). I want to record event times with microsecond precision.
From these web pages(https://docs.python.org/3/library/time.html, https://pymotw.com/2/time/index.html), I read that timestamps that I get by time.time() is calculated in UTC, but now I think something's different from what I read.
from datetime import datetime
import time
print( datetime.utcnow() )
print( datetime.fromtimestamp( time.time() ) )
>>> (executing file "<tmp 2>")
2018-03-16 21:28:34.716853
2018-03-17 06:28:34.716854
I don't understand why they are different. If timestamps are calculated in UTC, I think they should be the same.
I have another question. I'd like to know how to add some amount of time to timestamps. For example, I want to know how to do this with timestamps.
datetime.utcnow() + timedelta(hours=3)
datetime.utcnow() is the utc time, datetime.fromtimestamp() is the local time, which depends on your time zone.
To add to timestamp, you just need to convert the timedelta to seconds:
time.time() + timedelta(hours=3).total_seconds()
I have many strings of dates and times (or both), like these:
'Thu Jun 18 19:30:21 2015'
'21:07:52'
I want to convert these times to the proper datetime format while also changing the timezone to UTC. The current timezone is 4 hours behind UTC. Is there a way that I can tell python to add 4 hours while converting the formats? Can it also take care of the date in UTC such that when the hour goes past 24 the date changes and time resets?
I will ultimately be inserting these into a mysql table into fields with the 'datetime' and 'time' data type, but they all need to be in UTC.
I would approach this with time.strptime() to parse the source time string, time.mktime() to convert the resulting time vector into an epoch time (seconds since 1970-01-01 00:00:00), and time.strftime() to format the time as you like.
For the timezone adjustment, you could add 4*3600 to the epoch time value or, more generally, append a timezone string to the source and use %Z to parse it.
Hey all! Ive got timezone troubles.
I have a time stamp of 2010-07-26 23:35:03
What I really want to do is subtract 15 minutes from that time.
My method was going to be a simple conversion to unix time, subtract the seconds and convert back. Simple right?
My problem is that python adjusts the returned unix time using my local timezone, currently eastern daylight savings time which I believe is GMT -4.
So when I do this:
# packet[20] holds the time stamp
unix_time_value = (mktime(packet[20].timetuple()))
I get 1280201703 which is Tue, 27 Jul 2010 03:35:03. I can do this:
unix_time_value = (mktime(packet[20].timetuple())) - (4 * 3600)
but now I have to check for eastern standard time which is -5 GMT and adjust the (4 * 3600) to (5 * 3600). Is there any way to tell python to not use my local timezone and just convert the darn timestamp OR is there an easy way to take packet[20] and subtract 15 minutes?
Subtract datetime.timedelta(seconds=15*60).
The online docs have a handy table (what you call "unix time" is more properly called "UTC", for "Universal Time Coordinate", and "seconds since the epoch" is a "timestamp" as a float...):
Use the following functions to convert
between time representations:
From To Use
seconds since the epoch struct_time in UTC gmtime()
seconds since the epoch struct_time in local time localtime()
struct_time in UTC seconds since the epoch calendar.timegm()
struct_time in local time seconds since the epoch mktime()
where the unqualified function names come from the time module (since that's where the docs are;-). So, since you apparently start with a struct_time in UTC, use calendar.timegm() to get the timestamp (AKA "seconds since the epoch"), subtract 15 * 60 = 900 (since the units of measure are seconds), and put the resulting "seconds since the epoch" back into a struct_time in UTC with time.gmtime. Or, use time.mktime and time.localtime if you prefer to work in local times (but that might give problem if the 15 minutes can straddle the instant in which it switches to DST or back -- always working in UTC is much sounder).
Of course, to use calendar.timegm, you'll need an import calendar in your code (imports are usually best placed at the top of the script or module).
Scroll down and read about subtracting from a date: http://pleac.sourceforge.net/pleac_python/datesandtimes.html