My problem: I need to convert a UTC time-tuple into a UTC timestamp. But I have some confusions.
First a bit info:
Now let's do a test:
>>> from datetime import datetime
>>> import time
>>> import calendar as cal
>>> utc_now = datetime.utcnow()
>>> now = datetime.now()
>>> utc_now
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225)
>>> now
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903)
>>> time.mktime(datetime.timetuple(utc_now)), time.mktime(datetime.timetuple(now))
(1363439842.0, 1363425449.0)
>>> cal.timegm(datetime.timetuple(utc_now)), cal.timegm(datetime.timetuple(now))
(1363425442, 1363411049)
Why are there four different values? And which one is right when I want to convert a UTC time-tuple into a UTC timestamp?
UPDATTE
I think I have found answers to my confusions, so let me explain.
First, we need to know something important:
There are two kinds of date and time objects: “naive” and “aware”.
An aware object has sufficient knowledge of applicable algorithmic and political time adjustments, such as time zone and daylight saving time information, to locate itself relative to other aware objects. An aware object is used to represent a specific moment in time that is not open to interpretation [1].
A naive object does not contain enough information to unambiguously locate itself relative to other date/time objects. Whether a naive object represents Coordinated Universal Time (UTC), local time, or time in some other timezone is purely up to the program, just like it is up to the program whether a particular number represents metres, miles, or mass. Naive objects are easy to understand and to work with, at the cost of ignoring some aspects of reality.
What we get from datetime.utcnow()
or datetime.now()
are "naive" objects. This means that the datetime
object that is returned does not, in anyway, say anything about your local time or UTC time -- it just represents "some time". It just encapsulates date & time information (year, month, day, hour,minutes, seconds, etc.). It is YOUR responsibility to associate it with the notion of local or UTC.
So, remember that a naive datetime object just represents "some time". The datetime.now()
function returns a "some time" that is equal to your current time, and the datetime.utcnow()
function returns "some time" that is the current time in Greenwich England (which is what UTC is).
The "some time" is just a value for date & time. And note that on different locations on earth, the "some time" occurs on different times. For example, if a "some time" value is January 1, 10:30, than it will be the current time in Greenwich England some 5 hours BEFORE it becomes the current time in New York.
Hence we can see that there is two things: a generic "some time" value, and the notion that that "some time" becomes current time at different locations at different "times". (no pun here, read on)
Now, let's first define what is "epoch". We know that "some time" is just a generic value of time. Then, the epoch is a "some time" that occurred in Greenwich England where the values of the parameters are: January 1 1970, 00:00:00
.
A "timestamp" is no. of seconds that have elapsed since the epoch. This means that the timestamp was 0
when the time was Jan 1, 1970, 00:00:00
in Greenwich England. But the timestamp was approx. (5 * 60 * 60) when time was Jan 1, 1970, 00:00:00
in New York.
>>> tt = datetime.timetuple(datetime(1970, 1, 1, 0, 0, 0))
>>> cal.timegm(tt)
0
Thus, we can see that the same "some time" value of Jan 1, 1970, 00:00:00
has different timestamps when we change locations. Hence when you talk about timestamp, you need to also say "what location" is the timestamp related to, and how much eastward or westward that location is related to Greenwich England. That location is expressed as a "timezone".
Now, every system (computer) has a timezone configured, and all timestamps related to that timezone effectively become the "local". The UTC is the global reference.
So, let's say you have an X
value for "some time" which converts to:
Y
timestamp in your local time
Z
timestamp in UTC
then this means that Y
no. of seconds will have to elapse for "some time" to become the current time in your location and Z
no of seconds will have to pass in order for current time in Greenwich England to become "some time".
Now, finally, let's come back to our functions mktime
and timegm
. These take a time-tuple, which is just another representation for "some time". Remember that we're passing them a naive time which does not have any notion of local or UTC.
Let's say X
is a time-tuple representing a naive "some time". Then
mktime(X)
will return the no. of seconds that will have to elapse in order for your local current time to become that "some time", and
timegm(X)
will return the no of seconds that will have to be spent to make the current time of Greenwich England equal to that "some time".
In the example above, now
and utc_now
represent naive "some time", and when we feed these "some time" values into mktime
and timegm
, they simply return the no. of seconds that have to pass for the corresponding locations (your location and Greenwich England) to have their current time be that "some time".
Finally, back to my problem: I need to convert a UTC time-tuple into a UTC timestamp.
Firstly, there is no concept of "UTC time-tuple" -- it's just "some time". If I need to convert it to UTC, I simply use timegm
:
cal.timegm(datetime.timetuple(utc_now))
which will give me the timestamp for the current UTC time (i.e., the current "some time" in Greenwich England).
See Question&Answers more detail:
os