What happens when the clock of the computer running python (Windows or Linux)
gets automatically changed and a call time.time()?
I've read that the value of time.time() will be smaller when the clock is changed manually to some value in the past.
time.time() docs state:
Return the time in seconds since the epoch as a floating point number.
The particular epoch referred to here is the Unix epoch, which is Midnight, Jan 1st 1970 UTC.
Since it is always based on UTC, it will not be affected by changing the computer's time zone, nor when the computer's time zone enters or exits daylight saving time.
Though the function does rely on the underlying implementation to provide the value, those implementations always return values in terms of UTC - regardless of operating system.
On Windows in particular, it ultimately calls the GetSystemTimeAsFileTime OS function, which returns its value in terms of UTC. It is not affected by time zone selection or by DST changes within the time zone.
Quoting the docs for time.time,
While this function normally returns non-decreasing values, it can
return a lower value than a previous call if the system clock has been
set back between the two calls.
What adjusts the value of the system clock is platform dependent. But, per the comments, that shouldn't include changes based on DST, since all OSs that Python supports provide system calls for retrieving the current time in UTC (and DST only affects how local time relates to UTC).
If that isn't a good enough guarantee, you might prefer time.montonic, which is guaranteed to never go backward - however, note that it comes with this caveat (and decide whether this matters for your use case):
The reference point of the returned value is undefined, so that only
the difference between the results of consecutive calls is valid.
time.time() returns the value what the underlying library returns. Python uses time(..) or gettimeofday(.., nullptr) (depending whats available on the system).
https://github.com/python-git/python/blob/master/Modules/timemodule.c#L874
In both cases UTC is returned. E.g:
http://pubs.opengroup.org/onlinepubs/9699919799/functions/time.html
The time() function shall return the value of time in seconds since the Epoch
After a valid comment of Matt I have to add the definition of epoch which clearly states that time returns the UTC time.
Epoch:
Historically, the origin of UNIX system time was referred to as
"00:00:00 GMT, January 1, 1970". Greenwich Mean Time is actually not a
term acknowledged by the international standards community; therefore,
this term, "Epoch", is used to abbreviate the reference to the actual
standard, Coordinated Universal Time.
To proove the epoch is the same check this:
import time
a = time.gmtime(secs=0)
# time.struct_time(tm_year=2015, tm_mon=9, tm_mday=9, tm_hour=1, tm_min=3, tm_sec=28, tm_wday=2, tm_yday=252, tm_isdst=0)
b = time.localtime(secs=0)
# time.struct_time(tm_year=2015, tm_mon=9, tm_mday=9, tm_hour=3, tm_min=1, tm_sec=28, tm_wday=2, tm_yday=252, tm_isdst=1)
Both functions use the value returned from time.time() if the parameter secs is 0. In my case tm_isdst was set to true for the localtime, and false for the gmtime (which represents the time since the epoch).
Edit: Where have you read that the value will be smaller?
Related
I am measuring the response time on a function using the time module. The time module is supposed to output seconds as a float, so I am saving a start time value (time.clock()) and taking another reading at the end, and using the difference as a runtime. While watching the results, we noted the runtimes seemed high -- something that seemed to take less than 2 seconds, was printing as 3-and-change, for instance. Based on the perceived issue, I decided to double-check the results using the datetime module. Printing the two side-by-side shows the time module values are almost double the datetime values.
Anyone know why that might be?
Here is my code:
for datum in data:
start = datetime.datetime.now()
startts = time.clock()
check = test_func(datum)
runtime = datetime.datetime.now() - start
runts = time.clock() - startts
print(check, "Time required:", runtime, "or", runts)
Some of my results:
XYZ Time required: 0:00:01.985303 or 3.7836029999999994
XYZ Time required: 0:00:01.476289 or 3.3465039999999817
XYZ Time required: 0:00:01.454407 or 3.7140109999999993
XYZ Time required: 0:00:01.550416 or 3.860824000000008
I am assuming this sort of issue would have been noticed before, and I am just missing something basic in my implementation. Can someone clue me in?
Looks like time.clock() has been Deprecated since version 3.3
Maybe this will help ?
time.clock()
On Unix, return the current processor time as a floating point number
expressed in seconds. The precision, and in fact the very definition
of the meaning of “processor time”, depends on that of the C function
of the same name.
On Windows, this function returns wall-clock seconds elapsed since the
first call to this function, as a floating point number, based on the
Win32 function QueryPerformanceCounter(). The resolution is typically
better than one microsecond.
Deprecated since version 3.3: The behaviour of this function depends
on the platform: use perf_counter() or process_time() instead,
depending on your requirements, to have a well defined behaviour.
We found the issue. The test_func I am testing is using a multi-threaded process. I both did not know that, and did not know it was an issue.
The time module uses processor time (https://docs.python.org/3.6/library/time.html), while the datetime module uses wall clock time (https://docs.python.org/3.6/library/datetime.html). Using the difference in the datetime timestamps told me how much actual time had elapsed, and for our purposes was the relevant information.
I hope this helps someone else in the future!
I have a very simple code that is supposed to print out '2' every time the microsecond of the current time is 2, or once per second. However, when I run this code, it returns nothing. How can I fix this?
import datetime
while True:
if datetime.datetime.now().microsecond == 2:
print (datetime.datetime.now().microsecond)
You can't reliably build a loop that will only print exactly every second at the point where the number of microseconds in the current time is equal to 2.
Computer clocks don't necessarily tick every single microsecond, nor is Python always fast enough to produce a datetime instance for a given microsecond. On many systems, calling datetime.now() will produce the exact same value for several microseconds at a stretch, all the way up to only producing a new, distinct time once a second. Your code also creates multiple datetime objects, so after you test for the microsecond attribute, the next one created when you call print() may easily have a higher microsecond value.
See the time module which documents available clocks in a little more detail. datetime uses the same clock as time.time:
The precision of the various real-time functions may be less than suggested by the units in which their value or argument is expressed. E.g. on most Unix systems, the clock “ticks” only 50 or 100 times a second.
and
Note that even though the time is always returned as a floating point number, not all systems provide time with a better precision than 1 second. While this function normally returns non-decreasing values, it can return a lower value than a previous call if the system clock has been set back between the two calls.
It depends both on your OS and your computer hardware what the precision of your system clock is; it is not the resolution of the clock that matters (how much information can be given in the clock value) but rather how often that value is refreshed.
If you want to limit printing to once a second, just track the last time you printed and make sure the new time is at least 1 second newer:
import datetime
last = datetime.datetime.now()
while True:
now = datetime.datetime.now()
if (now - last).total_seconds() >= 1:
print(now)
What does python time and datetime module return on the leap second?
What will I get when we are at 23:59:60.5 if I call:
time.time()
datetime.datetime.utcnow()
datetime.datetime.now(pytz.utc)
Also, any difference between py2.7 and py3?
Why it is confusing (at least for me):
From the datetime docs I see:
Unlike the time module, the datetime module does not support leap seconds.
On the time docs I see there is "support" for leap seconds when parsing with strptime. But there is no comment about time.time().
I see that using time I get:
>>> time.mktime(time.strptime('2016-06-30T23:59:59', "%Y-%m-%dT%H:%M:%S"))
1467327599.0
>>> time.mktime(time.strptime('2016-06-30T23:59:60', "%Y-%m-%dT%H:%M:%S"))
1467327600.0
>>> time.mktime(time.strptime('2016-07-01T00:00:00', "%Y-%m-%dT%H:%M:%S"))
1467327600.0
And datetime just blows up:
>>> dt.datetime.strptime('2016-06-30T23:59:60', "%Y-%m-%dT%H:%M:%S")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
ValueError: second must be in 0..59
Then what will I get at that exact time (in the middle of the leap second)?
I have read about rubber times, clocks slowing down, repeating seconds, and all kind of crazy ideas, but what should I expect on python?
Note: In case you wonder if I don't have anything better to do that care about it, a leap second is approaching!!!!
Leap seconds are occasionally manually scheduled. Currently, computer clocks have no facility to honour leap seconds; there is no standard to tell them up-front to insert one. Instead, computer clocks periodically re-synch their time keeping via the NTP protocol and adjust automatically after the leap second has been inserted.
Next, computer clocks usually report the time as seconds since the epoch. It'd be up to the datetime module to adjust its accounting when converting that second count to include leap seconds. It doesn't do this at present. time.time() will just report a time count based on the seconds-since-the-epoch.
So, nothing different will happen when the leap second is officially in effect, other than that your computer clock will be 1 second of for a little while.
The issues with datetime only cover representing a leap second timestamp, which it can't. It won't be asked to do so anyway.
Python's mktime behavior here is pretty much just inherited from C's, which is specified by POSIX. The spec isn't as simple as you might think, and the reality is even more complicated.
I think this article is a good introduction to the various issues: The Unix leap second mess
The datetime module, as you observed, just acts like there is no such thing as a leap second.
This question already has answers here:
Does Python's time.time() return the local or UTC timestamp?
(9 answers)
Closed 7 years ago.
I need to generate a UNIX timestamp in UTC time so I'm using time.time() to produce it.
Do I need to do anything else or is the timestamp automatically in UTC?
Technically, time.time() doesn't specify, and practically, at least in CPython, it returns a timestamp in whatever format is used by the underlying standard C library's time function.
The C standard (which isn't freely available) doesn't say whether this is GMT, and neither does the POSIX standard. It just says:
The time() function shall return the value of time in seconds since the Epoch.
… without saying anything about timezone, except that you can pass it to localtime or gmtime to get a "broken-down time" in local or GMT timezones.
So, this is platform-specific. A platform can return anything it wants for time, as long as it does so in a way that makes localtime and gmtime work properly.
That being said, it's usually going to be GMT—or, rather, either UTC (Windows), or UTC-except-for-leap-seconds (most other platforms). For example, FreeBSD says:
The time() function returns the value of time in seconds since 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time, without including leap seconds.
OS X and most other *BSDs have the same manpage, Windows and linux/glibc also specifically return UTC (with or without leap seconds), etc.
Also, the Python documentation says:
To find out what the epoch is, look at gmtime(0).
Putting that together with the definitions for time and gmtime, it would be much more work for a platform to return local timestamps than GMT. (That being said, this statement can't be all that authoritative, because it's actually not quite true for any POSIX platform, thanks to leap seconds.)
time.time() returns seconds since epoch, so it doesn't define which time standard or zone is being used.
Convert to time standards using:
time.localtime([secs]) - Local time as defined by your operating system
time.gmtime([secs]) - UTC
They both return a time.struct_time.
>>> t = time.time()
>>> time.localtime(t)
time.struct_time(tm_year=2013, tm_mon=5, tm_mday=15, tm_hour=2, tm_min=41, tm_sec=49, tm_wday=2, tm_yday=135, tm_isdst=1)
>>> time.gmtime(t)
time.struct_time(tm_year=2013, tm_mon=5, tm_mday=15, tm_hour=0, tm_min=41, tm_sec=49, tm_wday=2, tm_yday=135, tm_isdst=0)
I have encountered a very weird situation in Python.
I have a while True: loop in a script that constantly grabs real-time data. The data is only meant to be grabbed during business hours, therefore I have a helper function in a module called lib/date.py.
This is the function:
def isTime(utc_now=datetime.datetime.utcnow()):
'''
9:00 AM UTC - 5:00 PM UTC Mon - Fri.
The parameter utc_now can be used to specify a specific
datetime to be checked instead of the utcnow().
'''
week_day = utc_now.weekday()
# no good on Saturdays and Sundays
if 5 == week_day or 6 == week_day:
return False
now_int = (utc_now.hour * 60) + utc_now.minute
if (17 * 60) >= now_int >= (9 * 60):
return True
return False
I realize that the way times are checked is an overkill, but this is a simplified version of my function. My real function also includes a bunch of time zone conversions which make the above necessary.
This is my main script (simplified):
def main():
while True:
do_ten_seconds()
def do_ten_seconds():
log.info("alive")
for i in xrange(10):
if isTime():
log.info("its time")
# do data grabbing
sleep(1)
This works perfectly during the week, stopping every week night and continuing the next morning. However, on the weekend, it does not "recover" from the long break. In other words, isTime never returns True Monday morning.
I checked the log, and the script just prints "alive" every 10 seconds, but the data grabbing part never happens (and "its time" is never printed). Hence, I am assuming this means isTime is returning False.
Could it be that because the function is called so frequently over the weekend, and because it returns False so many times in a row, Python caches the results and never recovers from it?
When I spawn the same instance of code while the main script is still running in the faulty mode where isTime is returning False, the new instance gets True from isTime and begins to work perfectly.
What is going on?
The first time you import date.py, the following line is run once:
def isTime(utc_now=datetime.datetime.utcnow()):
When it's run, the default value for utc_now is set to the time at that instant, and is never recomputed.
Default arguments are calculated at compile time. Make the default value None, and check for that using is None.