Assume a given variable, it is containing a UNIX
time-stamp, but whether it is in seconds or milliseconds format is unknown, I want to assign to a variable which i
An alternative to the answer given by Martin:
We've encountered this problem when we had to unify timestamps for documents coming in from 3rd parties. While the previous condition was:
if date > time.time():
use_miliseconds(date)
else:
use_seconds(date)
, and it seems like it should work, there are edge cases, especially if date
was derived from a string representation without timezone info, or the clocks are being changed.
A safer variant would be to use:
if date > time.time() + HUNDRED_YEARS:
use_miliseconds(date)
else:
use_seconds(date)
, where HUNDRED_YEARS = 100 * 365 * 24 * 3600
. This condition is much more error prone, in fact, it works for any date except January and February 1970 (which are ambiguous either way).
If you convert the maximum timestamp values with x digits in millis you get something like this:
Can your timestamps be older than 2001? If not i think you're safe to check whether the number has 13 digits or more - if yes you have milliseconds, if not you have seconds. Of course this will only work until timestamps in seconds will have 13 digits as well, which means timestamps in milliseconds will have 16 digits:
P.S. you can loosen up the condition to 12 digits or more, if your timestamps can't go back further than 1973. The condition should only be ok up until:
At the risk of attracting downvotes, I want to go on record as saying DON'T DO IT.
Making assumptions about the units of a physical quantity is a terrible idea - it led to the destruction of the Mars Meteorological Orbiter (the calculated units of thrust were in pounds, the engines expected Newtons. Not enough thrust - and the orbiter burnt up in the atmosphere).
If you have a pretty good idea of the magnitude of a number, you ought to be able to make an "educated guess" at the units. For example, if I tell you my weight is 230, you could look at me and think "I bet that is pounds, not kilos". Similarly, if you convert a time stamp of my birthday to a date on the assumption it was in seconds, and it turns out to be 200 years in the future, you can reasonably assume that "seconds" was the wrong unit.
But it is a DANGEROUS thing to do.
Still - if you have to do it, then in general, I would recommend the following approach:
That last thing is important - it will allow you to learn from your mistake. For example, if your time stamp tells you something about when the comet will next appear, you could print
Comet's next expected appearance: December 29, 2546 (assumption: time stamp from X was given in seconds)
In this way, there is some "come back". In general, "document your assumptions" is not just good advice - it is essential in any exact science.
Finally - the conversion of a time stamp from ms to s is achieved by dividing the number by 1000. But I'm sure you know that.
With your constraints, it is trivial to detect millisecond timestamps. Even timestamps a year into the past are still magnitudes larger than the current timestamp.
Simply test if the number is greater than the current timestamp; if so, you have a timestamp in milliseconds:
now = time.mktime(time.gmtime())
if t > now:
# milliseconds, convert to seconds
t /= 1000.0
By dividing by 1000, you convert the timestamp back to one expressed in seconds and the default time
module functions can be applied.
That's because even a timestamp in milliseconds representing one year in the past, accidentally interpreted as a timestamp in seconds, would lie far into the future:
>>> import time
>>> ts = time.mktime(time.gmtime())
>>> year_ago = ts - (86400 * 365)
>>> time.gmtime(year_ago * 1000) # misinterpret milliseconds as seconds
time.struct_time(tm_year=45395, tm_mon=7, tm_mday=9, tm_hour=14, tm_min=0, tm_sec=0, tm_wday=3, tm_yday=190, tm_isdst=0)
You'd have to have a timestamp early in 1970 before you could confuse the two ranges:
>>> now = time.mktime(time.gmtime())
>>> time.gmtime(ts / 1000) # misinterpret seconds as milliseconds
time.struct_time(tm_year=1970, tm_mon=1, tm_mday=17, tm_hour=5, tm_min=25, tm_sec=13, tm_wday=5, tm_yday=17, tm_isdst=0)
E.g. timestamps in the first 17 days after the UNIX epoch could be confused for timestamps in milliseconds. Everything after that date is going to be larger than a 'current time' timestamp.
With your specific constraints, you are lucky that we can keep the two units separate so easily. The better option is to not get into this situation in the first place. This data was sourced from somewhere; determine as early as possible what data type you have instead of having to guess later. No system will randomly give you timestamps in seconds some of the time, timestamps in milliseconds the rest of the time. Surely you can know based on other information what type of data you are sourcing and either convert at that time or annotate your data to include the type?