Monotonically increasing time in Java? - java

In a Java application I want to be able to take a timestamp at the start of an operation and be able to periodically check how long the operation has been running. The catch is: I do not want to be impacted by the Network Time Protocol moving the clock around, or the admin changing the time, or anything which can abruptly adjust the time of day. I want a monotonically increasing time value. I believe this rules out java.util.Date, Time, and Calendar.
Is there some source of a monotonically increasing timestamp in the JRE?

Have you considered using System.nanoTime()?
It is only meaningful in working out elapsed time between two events. Since the documentation states that it is not related to any system or wall time I believe it could be used in your sitatuion.

JodaTime has a class to do this. It is called Duration.
"They have no chronology or time zone, and consist solely of the millisecond duration."
Also you could set your Date stamp to Greenwich time and the Network Time Protocol should not be an issue.

Related

How can a 1 year old (java) lib correctly perform an UTC Time formatting, considering a newly introduced leap second

A timestamp expressed in milliseconds since 1.1.1970 UTC is a common way to store timestamps, e.g in Java.
e.g:
long timestampUtc = System.currentTimeMillis();
Such a timestamp can be formated in human readle time format, e.g using this code
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String humanTimeUtc = df.format(new Date(timestampUtc));
System.out.println(humanTimeUtc);
which gives output: 2014-02-14 14:58:05
Now imagine that today at midnight the time administration introduces a new UTC leap second.
If I run the code above tommorow, the java JRE on my system cannot know that leap second introduction, and would format the time wrongly (by one second).
Is my asumption correct?
How to correctly format the time (e.g in a log file) in systems that cannot always use an up to date JRE?.
Background info:
This is used in an embedded device, which synchronizes its system clock via GPS, having the GPS number of leap seconds offset to UTC.
Java and the Unix "epoch" (number of seconds since Jan 1, 1970 00:00:00 UTC) both ignore leap seconds entirely. They both assume every day (measured in UTC) has had exactly 86400 seconds. A simple block of code to verify:
Calendar c = Calendar.getInstance();
c.setTimeZone(TimeZone.getTimeZone("UTC"));
c.set(2014, 0, 1, 0, 0, 0);
c.set(Calendar.MILLISECOND, 0);
System.out.println(c.getTimeInMillis());
You will see that the number of seconds from 1/1/1970 to 1/1/2014 is an exact multiple of 86400 (it's actually exactly 44 years * 365.25 days/year * 86400 seconds/day); it shouldn't be, because there have been 25 leap seconds introduced in that interval.
If you need to take leap seconds into account, you need to find a library that will do so, or come up with your own adjustment.
Leap second handling is hard and Java is not particularly bad in this respect.
The NTP Timescale and Leap Seconds explains just some of the weirdness:
The insertion of leap seconds in UTC and subsequently into NTP and POSIX affect the system clock, and thus the conversion between system clock time and conventional civil time in hours, minutes and seconds. However, since the only institutional memory available to determine the conversion are the UTC national broadcast services, the conversion is in effect reset to UTC as each broadcast timecode is received. Thus, when a leap second is inserted in UTC and subsequently in NTP or POSIX, knowledge of all previous leap seconds is lost.
Another way to describe this is to say there are as many NTP or POSIX timescales as historic leap seconds. In effect, a new timescale is reestablished after each new leap second. Thus, all previous leap seconds, not to mention the apparent origin of the timescale itself, lurch backward one second as each new timescale is established. For instance, if a clock synchronized to UTC in 2005 was used to establish the UTC epoch of an event that occurred in early 1972 without correction, the event would appear 22 seconds late. As a result, for the most precise determination of epoch relative to the historic Gregorian calendar and UTC timescale, the user must subtract from the apparent NTP or POSIX epoch the relevant offset provided by the IERS. This is a feature of almost all present day time distribution mechanisms.
Leap seconds are almost never relevant unless you're doing astronomical calculations or something else that depends on the position of the Earth and Sun.
Usually people who think they need leap seconds really need either
a stable (for the foreseeable future) way of converting from a tuple representation like (year, month, day, ...) to a scalar representation like millis-since-epoch or
deal with one representation instead of mixing and matching.
I prefer (2). The scalar representation is better for scientific calculations, and the tuple representation is better for business and casual applications.
The answer by dcsohl and the answer by Mike Samuel are correct.
The other comments about the time database of Java being updated are incorrect. Yes, the database is updated, but not for leap seconds. Leap seconds are entirely ignored by Java, by Joda-Time, and by other Unix-oriented timekeeping systems.
Your question assumes a problem where none exists.
Clocks Drift
The physical clock on nearly all computers are not very precise. Drifting a second or more per month is common. That's why virtually all Operating Systems default to connecting to time servers either locally or over the internet. So, in practical terms, your computer is regularly tweaking its own current time. Because of this you may already find anomalies in the time sequences recorded in your logs if you looked carefully.
Inserting a leap second has the same effect as your clock’s imprecision. Your computer is off by a second, and will soon be corrected by a check-in with a time server.
Ignoring Leap Second
In terms of your data, both the bundled java.util.Date class and the popular replacement, Joda-Time, ignore the leap second. So think of a leap second as just stretching out that 59th second on the last hour of the day of a leap-second event. In terms of our calendar and call clocks, nothing happened. For all business-related apps and most practical purposes of most software, ignoring leap seconds has no detrimental effects.
Yes, technically speaking, the milliseconds-since-epoch used by java.util.Date and Joda-Time are incorrect. Right now is reported 1392442622998 since the beginning of the year 1970, while actually with 25 leap-seconds having been inserted since 1972, that number "should" be 1,392,442,647,998 (25,000 more). Yes, calculating the elapsed time between two timepoints over years will be short by a few seconds. But for most purposes, who cares? We have adjusted our calendars to act as if there was no extra second.
If you have a precision-oriented mind as I do, it takes a while to wrap your head around the fact that ignoring leap seconds has no practical effect on tracking the calendar. The basic problem:
Time-of-day is the way we read the spinning of the planet (which is slowing), while date/calendar is how we read the orbit of the planet around the Sun.
Those two, time-of-day & date/calendar, have nothing to do with each other. They are independent realities. But we humans smoosh them together to make sense of time the way we smoosh peanut butter and banana together to make a sandwich. And just like we might drizzle honey between the pb and banana to bring them together, leap-seconds bring the clock+calendar together in a unified manner for our mental consumption.
One Possible Problem
The only real practical problem is that reportedly some systems generate an actual 60th second, a time of 23:59:60. That time value wreaks havoc with some software written while ignorant of leap seconds. Such software incorrectly assumes that value is impossible, and may throw errors or otherwise fail. Properly informed software should know that (a) we can have extra seconds so 23:59:60 and 23:59:61 are legal values, and (b) the leap can be negative. (While so far we've had only single positive leap seconds, I recall reading that more than one is possible but not expected. I cannot find a source on that.) Remember, this problem only occurs if an OS or provider of time values is actually tracking those leap second events – few do, so they never see a second numbered 60.
More Info
Wikipedia page has more info on Leap Second.
My new library Time4J is able to handle leap seconds so this is one of several unique features of this library. I don't know any other library which can do formatting of leap seconds. Concretely about your question in detail:
Your example code using standard Java
SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
df.setTimeZone(TimeZone.getTimeZone("UTC"));
String humanTimeUtc = df.format(new Date(timestampUtc));
System.out.println(humanTimeUtc);
looks in Time4J like:
ChronoFormatter<Moment> formatter =
ChronoFormatter.setUp(Moment.class, Locale.US)
.addPattern("uuuu-MM-dd HH:mm:ss", PatternType.CLDR)
.build();
Moment timestampUTC = SystemClock.INSTANCE.currentTime();
System.out.println(formatter.format(timestampUTC));
// output: 2014-02-20 14:16:25
a) The time source SystemClock is based on System.currentTimeMillis(). This source never counts leap seconds and can also never yield a leap second timestamp - assuming that the underlying OS is leapsecond-unaware. So the output in this example will never display a leap second value of 60.
b) Internally an object of type Moment both holds a posix-timestamp AND a leapsecond-bit in its state. So by help of an external leapsecond table (which is actually hold in a small file in classpath) every Moment will correctly display the exact same time even when a system administrator will later update the leapsecond file and insert a new one. This does not affect any Moment outside of leap seconds hence there is no one-second-off-error. => If you rerun the code after insertion of new leap second then the timestamp of stored moment is still the same. The formatted output does not change which is a good thing.
c) You can construct a Moment which represent a leap second either by choosing a specialized time source (in the future I deliver a SNTP-client which might be able to track a leap second), or by applying a suitable number of SI-seconds added to a normal Moment. The formatted output for such a timestamp will indeed display a second value of 60, provided that the leap second table is up-to-date. If you transfer this leapsecond-moment to another JVM by serialization where the leapsecond-table is not up-to-date then it will be handled there as one second off (and if you serialize it back to a properly updated JVM or if the receiver-JVM is properly updated later then the leapsecond will be shown again).
d) Time4J also supports GPS time scale. You can construct a Moment by giving the elapsed seconds since GPS epoch (1980-01-06 midnight at start) and specifying the GPS time scale. Internally the Moment converts the data to UTC state which is not lossy provided the leapsecond-table is up-to-date. Of course, if your configuration is not up-to-date and the GPS source emits a number of elapsed seconds representing a leapsecond event then there will be an error one-second-off. In order to avoid such tiny and rare errors because of not properly managed leapsecond tables in client JVMs it might be a good idea to install another mechanism for configuration. Time4J defines a SPI-interface for this purpose.
We ran into this with C# on Windows as well using .NET's DateTime class: It does not take leap seconds into account even though the MSDN documentation appears to imply otherwise.
We decided to continue along with this as a known issue. One day, to work around this problem, we're planning on going back and adding something like a database table or a configuration file that can be updated in June/July and December/January to support and allow tweaking of the offset value to let us know today is exactly so many seconds--correctly accounted for leap seconds.
If anyone has any other bright ideas in C# or Java, we'd love to hear them. Thanks.

CurrentTimeMillis changing, any possible reason?

when System.currentTimeMillis changed, what will be the possible reason?
say the currentTimeMillis changed 1 and 2 minutes hour only after 2 minutes. Related to day light saving?
One possible reason is the time is synced to the correct time , what will be the other possible reason?
I will just begin guessing - mainly I see 2 possible reasons:
You are writing the conversion from milliseconds since 01.01.1970 00:00UTC by yourself and did somwhere a mistake (we going to need the code)
There is some point when actually the return value makes a jump of 3600000 (such jumps will only happen if you change the System clock, or maybe you update the time using NTP)
System.currentTimeMillis(), according to its documentation, returns the the difference, measured in milliseconds, between the current time and midnight, January 1, 1970 UTC. So obviously it's changing rapidly all the time. The caveat is that it refers to wall clock, which could be adjusted anytime!
That is, it will jump an hour because of daylight saving time an arbitrary amount if someone or something - possibly an automated NTP synchronizer - simply adjusts the computer's clock or date. If you need to measure how long something takes, you should use a timer, e.g. System.nanoTime(), which is guaranteed to change monotonically, not a clock (which is supposed but not guaranteed to refer to some fixed point).

System.currentTimeMillis() is a good choice for this?

I'm still not sure how System.currentTimeMillis() work, but I want to use it for a game server to handle Banned accounts.
For example, in data base I will have a "bannTime" which will equal (System.currentTimeMillis() + How_much_time_to_ban_in_ms ) in the user's data.
When the user will login, it will always check if it's OK using this:
if(bannTime==-1)return;
if(System.currentTimeMillis()>bannTime){
// It's ok you can long in
removeBanFromDataBase();
}else{
// You can not login, you have to wait: (bannTime - System.currentTimeMillis())
return;
}
What I need to know is:
Is it safe to use System.currentTimeMillis() like this as long as the code will always run on one machine ? Even if I reboot the machine, System.currentTimeMillis() will keep incrementing and never go back or start from zero ? Never ?
And what If I change the local time and date on the machine, System.currentTimeMillis() will change too ?
System.currentTimeMillis() will never reset to 0. It is the number of milliseconds since the Epoch, way back at midnight, January 1, 1970.
This approach is fine, and it's often easier to do maths with milliseconds, as you're finding out.
Ref: http://download.oracle.com/javase/6/docs/api/
edit: good point Spycho, the currentTimeMillis() response is based on the system clock, not magic, so changing the system time back by a couple of days would make the number decrease. But not in normal practice.
If you're using time to ban users, you will probably want to use an NTP service to keep your system clock correct (if you're not already).
System.currentTimeMillis() may go back (or leap forward) if the system clock is changed.
If this code is running on the server side you should be fine.
Due to leap seconds (or manual clock changes) the time on the server can change, but it shouldn't change by such a large amount that it actually matters if the ban is revoked too early.
You should, of course, ensure that the server is set to get its time via NTP, so that it's always as accurate as possible, and correctly set on reboot.
you could use a combination of that in addition to writing a file on the system and storing the timestamp/related information in the file
System.currentTimeMillis() is always the actual time, in milliseconds since midnight 1st January 1970 UTC, according to the local system. If you change the time on the machine, the output of System.currentTimeMillis() will also change. The same applies if you change the machine's timezone but leave the time unchanged. System.currentTimeMillis() will never reset to zero (unless you change the machine's time to be whatever the time was in the machine's timezone at 00:00:00.000 on 1st January 1970).
System.currentTimeMillis() should be fine for what you want to do.
You may like to set a `reboot counter (or program restart counter),' which is persistent (in db or file), to distinguish time-stamps recorded in different boot sessions.
And then record your time-stamp by the combination of System.currentTimeMillis() and the counter's value
When the reboot counters are different for two time-stamps, you may deal it differently from normal cases. Maybe launching a time synchronizing routine or something.
When using System.currentTimeMillis() you are getting the time of the System, in other words the time of the machine you are running your code on. So when you restart your machine, you will still get its time that will increment even when the machine is turned off for sure.
But when you change the time of the machine, System.currentTimeMillis() will get you the new time, the time you changed. So when the time is changed you will get wrong time.
I used this in many classes without holding the matter of changing the clock. You can just use it with only this risk. But I find it a very good choice to work on.
An alternative would be to use System.nanoTime() because a) its more accurate and b) its monotonically increasing. However its slightly more cumbersome to work in nano-seconds, and its highly unlikely to make any real difference, unless your system clock varies wildly by seconds or more. (In which case you are likely to have other problems)
just test this code.
change time while running this code.
System.currentTimeMillis() stops printing out when system time is set back.
it starts printing again when time > time_before_setting_back
while (true){
System.out.println(System.currentTimeMillis());
try {
Thread.sleep(1000);
} catch ( InterruptedException e ) {
e.printStackTrace();
}
}

How to get time delta independently from system time?

I'm writing a simple timer in Java. It has Start and Stop buttons, along with a text view showing how much time has passed since the timer was started.
It's implemented by setting initial time with System.currentTimeMillis() and updating current value each second in a loop.
The problem is that if I change system time while the timer is running, the whole measurement fails. E.g., if I set time back one month, the timer shows negative value as currentTimeMillis() now returns less value than initial.
So, how do I calculate time delta which would be independent from the system time? It would be also great to make this solution cross-platform.
Use:
System.nanoTime()
This should do it. It doesn't take the system time into account, and can only be used to measure elapsed time. Which is what you want. You need to divide by 1 million to get the elapsed milliseconds. See also the Javadocs.
System.nanoTime();
From Javadoc:
This method can only be used to measure elapsed time and is not related to any other notion of system or wall-clock time.
Use time web services . for example this or this or this
You can install demon like NTP, system time jumping in any directions has a lot of issues and can lead to quite a lot of other problems.
System.nanoTime() not necessarily depend on the system clock - but it can - just make sure the system time is correctly progressing.
Modifying system time is a privileged operation, so it someone does that they shall know better.
Here is a bug 13 years of age regarding the same case: http://bugs.sun.com/view_bug.do?bug_id=4290274
HTH

Detect if system clock changed?

I am looking at the idea of a Java project that detects when the computer clock has been changed. The idea is to record the date and time on the computer clock and store it in a file. I then want to be able to run rules on it that shows a message if the clock has been changed. I am also looking at incorporating rules such as "Allowing no more than 5 minute changes". This is to allow convenience of changing the time by the odd minute.
I also need to incorporate the changes that the clock makes. E.g., going forward an hour or back an hour at certain times of the year (British Time).
I am not sure if there is already a Java system that does this that I could look at but I literally don't know where to start with this.
Java gets all it's time/date information from the system clock anyway, so there's no way of knowing if the underlying system clock has been changed. If you take the date and time and store it in a file - that will detect if the time has been set back (i.e. - the time in the file is after the current time, and no DST has occurred) - but it can't detect if time has been set forward (i.e. - the time in the file is 2 hours before the current time - has 2 hours really elapsed, or has the user set the clock ahead by 2 hours while the program wasn't running?). The only way you could do something like this is use a known Time Server, and instead of saving the time in the file, save the offset between the time server and the local system clock.
If you can rely on the presence of a network connection, you could compare the time with the time from an internet time server (CBATG).
Simply convert the local time and a fetched time to the same time zone and store the difference. If the diff changes by more than the allowed amount of 5 minutes, you know it's been modified.
If I understand your question right, then what you are trying to do assumes that initially, the system clock is at the optimal state. Then, after every minute you retrieve the last entry in the file (either the last or the first, whatever method you chose) and make sure that the difference between the two times is either 60 seconds or any other time interval you choose.
Example:
At time 0, you place in the file 12:00:00
At time 1, you compare 12:01:00 (which you retrieve from the system clock) with 12:00:00 (which you retrieve from file)and deem that it is alright and write it to the file.
...
At some time n, you compare xx:yy:zz whose difference with the last entry is not 60 seconds, so a change has been detected.
...
I believe the rules you're talking about involves taking the last entry from the file and doing a comparison with the current time you retrieved from the system clock. Whether or not this is a good method however, is arguable.
First: The clock changes veeeery often. Try using java.util.Timer for updating. Calender is for your time system.
http://java.sun.com/javase/6/docs/api/ is your friend in this.
Start small, one step at a time. That's my advice.
A good place to use the Joda time library. In theory, you only need to check if the local timezone has moved between DST and non DST state - if you don't want to check for local time shifts.
I haven't tried this, but it might work to have a background thread which wakes up once a minute, gets the current time, and compares it to what it last saw. Theoretically, the difference should be very close to one minute. If it differs much from that, that would mean the clock changed.
You seem to be asking for two very different things:
When a user or system administrator causes the computer’s clock to be adjusted or corrected to a certain moment (either to set to the true current date-time or to another past/future date-time for either testing or nefarious purposes).
When the displayed hour-minutes change for an event such as Daylight Saving Time (DST).
Clock manipulations
For the first, no good simple way to do that. You could occasionally sample the current date-time, record it, then sample again later. You would do this in UTC to avoid mistaking DST autumn changes as a user/sysadmin alteration.
Example code using the java.time classes. Avoid the old outmoded non-java.time classes as they are poorly designed, confusing, and troublesome.
Instant now1 = Instant.now(); // Record, run again, compare.
String now1AsString = now1.toString(); // Ex: 2011-12-03T10:15:30.724Z
…
Instant now2 = Instant.now();
Boolean timeWentBackwards = now2.isBefore( now1 );
Of course you cannot use this technique for adjusting into the future, only the past. The clock is always moving into the future.
The only reliable way to detect molestation of the clock is to have more than one clock. You need have trusted access (connection) to a trusted clock, probably either a time server on your network or a time server on the Internet. Even then, having only a pair of clocks can be tricky. As the old sea-faring adage says, “Bring aboard one compass, or three.”.
DST roll-overs
Detecting DST changes should be irrelevant. The general best practice in handling date-time is to work in UTC. This includes most of your business logic, your data storage, and your data exchange.
Remember: The time-of-day rolling forward or backward with DST is meaningless -- time continued to flow, not warp, with the same number of seconds passing.

Categories

Resources