How to test if a given time-stamp is in seconds or milliseconds?

48,344

Solution 1

If you convert the maximum timestamp values with x digits in millis you get something like this:

  • 9999999999999 (13 digits) means Sat Nov 20 2286 17:46:39 UTC
  • 999999999999 (12 digits) means Sun Sep 09 2001 01:46:39 UTC
  • 99999999999 (11 digits) means Sat Mar 03 1973 09:46:39 UTC

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:

  • 1000000000000000 (16 digits) means Fri Sep 27 33658 01:46:40 but by then i will be living on a planet from the Alpha Centauri system and time standards will probably have changed a bit :)

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:

  • 100000000000000 (15 digits) means Wed Nov 16 5138 09:46:40 because this in seconds will have 12 digits and will overlap with your condition

Solution 2

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:

  1. Given all the possible units, make the conversion to a "sensible" scale (for example, convert your time stamp to a year/month/day).
  2. Look at the values you obtained. Which of these is "most likely". In the case of dates, you might have a good idea (date this computer came into service: was it 1970 or 2012? etc)
  3. Choose the value that is most likely
  4. Record somewhere that this is what you did - so that if the consequences of this decision turn out to be wrong, you can trace the error

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.

Solution 3

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?

Solution 4

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).

Share:
48,344

Related videos on Youtube

Ryan
Author by

Ryan

Updated on July 09, 2022

Comments

  • Ryan
    Ryan almost 2 years

    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 is in seconds format

    For Example:

    unknown = 1398494489444 # This is millisecond
    t = ???
    

    Updated: I understand it is not possible to tell without giving some limitations, so here is it

    • current_ts - 86400 * 365 < unknown < current_ts

    Assume current_ts = current unix timestamp

    • frlan
      frlan almost 10 years
      Without knowing more I'd say it's impossible. As e.g. 1970-01-01 is the same in ms as in s.
    • Ryan
      Ryan almost 10 years
      @frlan, okay, except the 0
    • frlan
      frlan almost 10 years
      Well. what's with 10ms after 1970-01-01 and 10s after 1970-01-01 ... looks pretty much the same as ms or s for the second one.
    • Jasper
      Jasper almost 10 years
      @Ryan how would you (manually) decide if a number is ms or s after the Epoch?
    • Ryan
      Ryan almost 10 years
      @Jasper, I've updated the question
    • Vincent Savard
      Vincent Savard almost 10 years
      It's not possible unless there is a context clue around the timestamps. Do you know around what actual date it is? Does the interval of possible times in second overlaps with the interval of possible times in milliseconds?
  • Uyghur Lives Matter
    Uyghur Lives Matter almost 10 years
    I may missed something, but I think you meant t /= 1000.0 instead of 10.0 to convert seconds to milliseconds.
  • Martijn Pieters
    Martijn Pieters almost 10 years
    @cpburnz: ick, no I missed something. Updating.
  • Floris
    Floris almost 10 years
    To the extent that this question can be answered, yours is a very sensible approach and should be the accepted answer. Having said that, I would like you to add "making assumptions about the source of data is no substitute for verifying". Trying to guess the units of time is a terrible idea. No physical quantity should ever be communicated without units. Anything else is terrible practice. Just remember the Mars climate orbiter blunder
  • Martijn Pieters
    Martijn Pieters almost 10 years
    @Floris: added an admonition about determining the type early.