Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get International Atomic Time in Java 7

I am working on a Java7 project, and we need a timestamp in International Atomic Time. I've found a few other questions relating to this that point to JSR-310 and ThreeTen Project (which is implementing JSR-310):

How to get GPS Time and TAI time in Java?

http://www.coderanch.com/t/549178/java/java/TAI-Atomic-Time-International

However, I'm struggling to work out exactly what to use for Java 7 and where to get it from. There seems to be old SourceForge & GitHub pages for ThreeTen, as well as an OpenJDK page.

I've found the Java 7 backport, but after downloading this from Maven it doesn't include the TAIInstant class, which is what I actually need (the TIAInstant class is listed on the ThreeTen SourceForge JavaDoc, under javax.time.TAIInstant).

For completeness, this is the excerpt from my pom.xml:

<dependency>
  <groupId>org.threeten</groupId>
  <artifactId>threetenbp</artifactId>
  <version>0.8.1</version>
</dependency>

Should I be using something else, and where should I be getting it from?

Note: Sorry I'm not able to provide links to all the pages I'm referring to, StackOverflow won't let me have > 2 links per post without higher rep.

[EDIT] The reason for wanting TAI is that I need a timestamp which is monotonically increasing, which I believe TAI fulfils (even during both positive & negative leap seconds, since it doesn't care about leap seconds counts all seconds equally, including leap seconds).

Having read about POSIX / Unix time from various sources it's still not clear to me exactly what happens in Unix Time over a leap second. I know the Unix Time is ambiguous in terms of referring to a UTC Time, but I'm not clear on what happens in Unix Time in the instant a leap second occurs? Does Unix Time 'pause' or go backwards for example? And perhaps more importantly, even if it shouldn't according to the Unix Time spec, do Unix implementations actually obey the spec regarding leap seconds...?

Finally, Am I correct in saying that System.currentTimeMillis() will get the equivalent of POSIX Time (albeit in milliseconds rather than seconds)?

Note, I need an object which is portable across JVMs and machines (ruling out System.nanoTime() or similar).

[CONCLUSION]

TAI
TAI is a system of measuring time where every second is counted and 'all seconds are equal' - ie. every second consists of the same period of time, and all seconds (including leap seconds) are counted in the total. This means the number of seconds in TAI (counted from some arbitrary start point, the Unix Epoch for example) is a monotonically increasing integer.

POSIX Time
POSIX Time is a standard (NOT an implementation) for measuring time. It defines every day as having exactly 86400 seconds. Therefore, POSIX time does not count leap seconds (since occasionally a minute may have 61 seconds, leading to days with >86400 seconds, and theoretically a minute could have 59 seconds, leading to days with <86400 seconds). This means that 'seconds' in POSIX have variable length, and shortly before / during / after leap seconds, a POSIX clock may skip seconds or repeat them. Specifically, the POSIX spec as referenced by Meno Hochschild in his answer states, "The relationship between the actual time of day and the current value for seconds since the Epoch is unspecified."

UTC
UTC is a time standard which is related to the way the Earth moves around the Sun, aiming to maintain the relationship between the position of the Sun and the time of day (within a threshold). Ie in a UTC+0 region of the Earth, the Sun is always at its highest at midday UTC time. Leap Seconds (positive or negative) are necessary because the speed of the Earth's rotation is not fixed, and it does not vary in a predictable way (meaning we cannot predict when leap seconds will be necessary - or whether they will be positive leap seconds or negative leap seconds)

Representing Times
It seems to me that both TAI and POSIX are representations of 'counts of seconds' (ie. something easy for a computer to actually store), whereas UTC is a 'human interpretation' of time (ie. Year/Month/Day Hour:Minute:Second.millisecond) that is not usually stored internally by a computer.

Translating Times
Given the above, there are a number of issues translating from POSIX (without any leap seconds counted) to TAI (with leap seconds counted):

  1. It requires maintaining a table / count of leap seconds to translate any POSIX Time to a TAI Time
  2. Even if point 1 is addressed, the POSIX Spec as above makes no guarantee about what will happen during a leap second, so at such times we have no way of accurately representing an unambiguous time
  3. If a number of systems must communicate, passing timestamps between them, we must guarantee that the table / count of leap seconds is kept consistent

On the other hand, it is easy to convert from POSIX to the UTC 'human interpretation'. It doesn't require knowledge of leap seconds, since it just assumes every day has the same number of seconds (albeit some of these 'seconds' have different lengths of time in reality). In practice, you would just use the inverse of the formula in the POSIX Spec to obtain various the UTC components of time (again, see the POSIX spec referenced by Meno Hochschild).

like image 336
asibs Avatar asked Dec 23 '13 15:12

asibs


2 Answers

The class TAIInstant, and others like UTCInstant were removed during the JSR-310 process. The group came to the conclusion that these were specialist items and not necessary to be in the core JDK. I still believe this to be the correct decision.

The result of this is that there is very little support for time-scales in JSR-310. However, there is a formally defined way to connect JSR-310 to time-scales, allowing an accurate clock to be created given an accurate source. While not everyone likes this solution, it is practical for the mainstream.

In summary, the original design of separate classes for UTC and TAI is sound (and necessary to handle events in the past and future). However, it was too specialist for the JDK.

The threeten-extra project is now available as a jar for JDK 8 with these classes in.

like image 137
JodaStephen Avatar answered Oct 23 '22 06:10

JodaStephen


The JSR-310-backport only supports features which will be included in Java 8. TAI (and true UTC) will not be a supported feature hence it cannot be in backport. The only alternative would be to try the threeten-extra-project which contains the class TAIInstant but the whole extra-project might not be up to date (very old code).

I am myself working on my library Time4J which has TAI-, GPS- and UTC-support in addition to POSIX.

[UPDATE from July 2014: Time4J is now available as stable release time4j-v1.0. This debate has been taken into account - see for example Moment.toString(TimeScale) .]


Correction and detailed remarks to newly posted questions of OP:

a) Yes, TAI is monotonically increasing in units of SI-seconds even during leap seconds. If it is only that what you wants you might choose TAI, but there is a pitfall. If you want to describe civil timestamps then TAI will give you wrong timestamps (just compare the first and the second column of Wikipedia diagram). The reason is simply that civil life is ruled by UTC, not TAI.

b) About my comments that Wikipedia diagram is wrong, I have looked again at it very closely and changed my mind. The relation between POSIX and TAI is not fixed (10s offset only in 1972), so please excuse my error. Until now I have not thought so much about TAI, rather about POSIX and UTC. But thanks for the question and this enlightening debate so you deserve my upvote. The whole thing is tricky. When we talk about timestamps represented in different time scales we need to make a difference between the ymdhms-form and the epochsecs-form. Let's consider it in detail for the time 1999-01-01T00:00:00Z (UTC-scale):

  i) TAI = (29 * 365 + 7) days * 86400 + 22 leap seconds + 10s (offset at 1972) = 915148832
 ii) UTC = TAI - 10 = 915148822 (fixed relation between UTC and TAI on epoch-second-level)
iii) POSIX = UTC - 22 leap seconds = 915148800

=> (ymdhms-form);
  i) TAI (915148800 + 32) = 1999-01-01T00:00:32 (based on TAI-"day" = 86400 SI-secs)
 ii) UTC = 1999-01-01T00:00:00 (stripped off former 22 leap secs in conversion to ymdhms)
iii) POSIX = 1999-01-01T00:00:00 (fixed relation between UTC and POSIX with exception of leapsecs)

So why the statement that TAI does not count leap seconds? It does not count leapsecs in ymdhms-form, but of course it counts them on epoch-second-level (monotonicity requirement!). And POSIX? It does not count leap seconds at all, neiter in ymdhms-form nor on epoch-secs-level. So finally we have no fixed relation between TAI and POSIX. A leap second table is required for conversion.

c) What does POSIX spec tell about leap second behaviour? See here. Especially note the statement: "The relationship between the actual time of day and the current value for seconds since the Epoch is unspecified." So this concerns the leap second, too. It is up to clock implementations if they jump before the leap second or jump after or freeze for one second.

d) Yes, System.currentTimeMillis() will get the equivalent of POSIX Time (albeit in milliseconds rather than seconds).

e) Just to note, the label TAI is not defined before 1971 and International Atomic Time not before 1958, so the proleptic scale of threeten-extra-class TAIInstant is somehow nonsense. So I would not apply TAI before 1972. Here I go with Steve Allen, the expert in time scales.

f) If you need a time object which is "portable across JVMs and machines" then UTC itself requires the distribution/existence of the same leap second table everywhere. If you choose TAI you still need this leap second table in order to enable applications to convert TAI-timestamps into UTC- or POSIX timestamps. So I doubt that you can have a monotonically increasing timestamp and ignore leap seconds simultaneously. TAI does not offer a solution for this dilemma.

Answers to question/summary of OP from 2013-12-31:

Your summaries about TAI and POSIX are correct.

About UTC, you should above all understand that UTC is a compromise. On the one side it is designed to follow the sun, on the other side the second on UTC scale is exactly the same as on TAI scale, namely the SI-second (atomic definition). You are right when you stated that the earth rotation speed is unpredicably slowing down, so leap seconds are some few times inserted. The difference between UT1 (mean solar time) and UTC shall always be smaller than 0.9 SI-seconds. So this and the fact of equal SI seconds are the core ideas of UTC. As an aside, the adaptation of the exotic UTC-SLS scale in JSR-310 is not compatible with these core ideas of UTC. About predictability of leap seconds, the BIPM in Paris announces every half year if 6 months later there will be a leap second necessary or not, so you have this predictability frame of six months in advance.

One maybe pedantic correction about UTC section, you wrote: "the Sun is always at its highest at midday UTC time." A similar statement is also given in the javadoc of class java.time.Instant about the so called java time-scale. Left aside the fact, that you surely not wanted to say that the position of the sun is independent from your local position, it is not even correct at the right longitude at midday. Why? From an astronomic/scientific point of view you should first not forget that the mean solar sun time is not the same as the true local solar time which you watch (just giving the keyword "equation of time"). Furthermore, since UTC is still based on atomic time and uses atomic time for synchronization, there is a so called delta-T-relation between UT1 and UTC. This delta is within the frame of 0.9secs and is published regularly by IERS/BIPM in the bulletin B. You need to know this delta when you want to get the real position of the sun and when the sun is highest.

The section "Representing Times" is in my opinion a little bit too simple. Okay, we can say that TAI and POSIX count seconds while UTC is rather represented in year/month/day/...-form. But we can indeed apply both representations to all scales. But we need to carefully differentiate between these representations and think thoroughly about how to convert. Note that Wikipedia has even choosen the ymdhms-form for TAI in the diagrams. Well, computers can best store simple integers. And POSIX or TAI can easily be stored in that format. But as I said before, the interpretation of these integers is not always simple. In case of TAI you even need a leap second table to convert to readable civil ymdhms-form (either UTC or POSIX).

About the next section "Translating Times", I agree with points 1-3.

Your final statement "On the other hand, it is easy to convert from POSIX to the UTC 'human interpretation'." is right with exception of leap seconds. Well, I enable a suitable translation between the different scales with my coming library. It has a built-in but configurable leap second table, and in future I also plan to use IANA-TZDB-data as source for such a table.

All in all be aware of the fact that most business developers have no need for so much accuracy. Most people will simply equalize POSIX and UTC and will probably be satisfied with any smoothing hardware solutions in Linux OS or on Google NTP servers. True UTC and TAI (that is taking in account leap seconds) require more efforts. So you have to decide if your software architecture needs scientific accuracy.

And just to note, JSR-310 officially does not address the very wide-spread scale POSIX at all, instead they say, their class Instant shall be UTC-SLS by definition (see also this interesting debate).

Finally I am graceful for this discussion. It has also helped me to clarify my thoughts about TAI in my library. Thanks.

like image 36
Meno Hochschild Avatar answered Oct 23 '22 06:10

Meno Hochschild