Paul said:
The are any number of such special reference frames, but for everyday
purposes, you can subtract two millisecond values in Java and get something
useful and consistent.
One old point:
The OP and the arguments about that code were about calculating differences of
days, not raw differences in milliseconds, second, minutes or hours
Now on to increasing millisecond sequences regardless of the whether you want
them for subtraction of days, hours, minutes or seconds.
Thomas Marshall asked:
On all machine, in all locales, is the progression of java
milliseconds guaranteed to be linear?
In Java the VM relies on the underlying OS which relies on the hardware,
therefore even a VM running in a special frame would consistently return
whatever the hardware tells it. As Paul L. mentions we can ignore such odd
special reference frame cases, but the gotcha is the hardware/OS value.
We can ignore locales and timezones, since the millisecond value is **supposed**
to be GMT, again to the limit of the machine, so assuming the underlying
hardware counts up then:
Answer 0: Yes, the java.util.Date millisecond value will be an ever increasing
sequence.
You can run one of those little NTP synchronizers that keep you OS/hardware
clock sync'ed. For more information about Network Time Protocol see:
http://tycho.usno.navy.mil/ntp.html
"Typical accuracy achieved is in the range 1 - 30 ms continuous, and is highly
dependent on the symmetry and speed of the Internet path between client and
server. Best results are achieved using a combination of servers which are
closest to the client in a network sense."
So how could this effect a java millisecond values?
The value is apparently only good on your machine (not the NTP server which is
often better) to 30 ms. For example, one NTP request might want to set your
system clock ahead 20 ms, but then after the network is less busy, the next NTP
check comes up with a closer value and wants to set it back maybe 15 ms.
Answer 1: NO, the sequence is not guarenteed to be increasing, because
theoretically there could be jump backs in the millisecond value, since running
NTP could result in resetting your clock up or down by something in the range of
1 - 30 ms.
Since it is the resetting of your system clock downward by something akin to NTP
which is where the potential problem lies, you could have something that might
be even more noticable on a system which
a. drifts noticably forward over a longer period (that is it's seconds are too
short, so counts too fast)
b. runs NTP infrequently enough that this drift is noticable.
Answer 2: NO, there might be jump backs in the millisecond sequence if you have
a system clock which drifts ahead in time and NTP service run infrequently
enough to produce a noticable jump back.
The above are listed in increasing size of jump backs in time.
The above only apply when you create a new java.util.Date/java.util.Calendar
based on the current time. Many applications make up values for "midnight", "8
AM" "last Monday", "End of the Month" using calendar calculations disconnected
from the actual local time.
A few solutions to work around the NO scenerios are to:
1. Run NTP often enough to stay within a minute or so and be willing to work
with time instances which are slightly off and thus
-- pay the guy/girl whose hours you just calculated an extra 3ms, 0.3
minutes or even 3 minutes!
-- bill the user who connected to your system to whatever the clock said.
Because often no one is going to worry about fractions of seconds or even a
minute or two.
I'm sure you aren't going to get far with a cell phone company with a letter:
"To whom it may concern, It has come to my attention that according
to my calculations, your reconds for the remaining balance for my
cell phone has lost 12.52 seconds ... I would appreciate being given
a credit for your incorrect calculation" hahaha.
2. Run NTP often to keep within a few 10's of ms range, then round to an
application appropriate value.
-- if you are actually worried about 1/10ths and you can't suffer
being off by a second or a 1/10th now and then (see previous solution)
then whenever you create or us a millisecond time value from the
system clock, you could round it to the appropriate precision.
3. Run a machine directly connected to a radio synchronized atomic time value
(see
http://www.boulder.nist.gov/timefreq/stations/wwvb.htm) or able to NTP over
a quiet network (same town or better late at night) to such a time reference to
keep to a much closer time value than the 30ms value.
Personally, I have always taken solution #1 -- being willing to accept being off
by a small amount of time. Many network applications are built with some
variation of solution #2. People who _really_ care usually take solution #3.
A much bigger and more application noticable problem are scenerios which we have
hinted at, but wanted to avoid, so haven't addressed in this thread. I list
some of those below.
Common Error 1: Non-synchronized clocks
A common error scenerio are clients and servers which don't run NTP, exchange
times which are off by an application noticable amount. I used to get this all
the time when checking in files between a machine in (North American) 'Mountain
Time' and machine in 'Central Time' not all of which were running NTP despite
some variation of solution #2 being part of the older/newer check used in the
application.
Common Error 2: Forgetting TZ or DLS offsets
Another common error scenerio is to miscalculate timezone offsets so report
inappropriate milliseconds since 1/1/1970 thus throwing an hour or more error
into the mess.
Common Error 3: Running one machine on a timezone other than local time.
A really obvious error is a machine which is set to run its OS clock on GMT, but
the machine is located somewhere else. For example, a user leaves the timezone
on GMT, then sets the clock to read correct local time -- let's say New York
time -- but since the machine is set to GMT, the VM runs on GMT, thus any
reported millisecond time is off by the current difference between New York and
GMT Time.
Summary
Java relies on the OS which relies on the hardware to deliver millisecond
timestamp values. If the OS can change the value down, for example through
running a NTP time synchronization client, the time values are not guaranteed
to be an ever increase sequence. This is charateristic of the underlying
machine not of a Java date (timestamp) value. In order to deal with this
potential problem you can use a combination of frequent enough NTP resets and
rounding of time value to an appropriate precision. More common errors are to
be off not by parts of minutes, but by hours due to timezone errors.
HTH,
-Paul