I was trying a proof of concept for using java.time.instant for a certain requirement. I ran into something I couldn't explain. I was wondering if someone could explain how this happens.
package NanoDate;
import java.time.Instant;
import java.time.Period;
import java.time.temporal.ChronoUnit;
import static java.time.temporal.ChronoUnit.DAYS;
import static java.time.temporal.ChronoUnit.HOURS;
import static java.time.temporal.ChronoUnit.MILLIS;
import static java.time.temporal.ChronoUnit.MINUTES;
import static java.time.temporal.ChronoUnit.NANOS;
import static java.time.temporal.ChronoUnit.SECONDS;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/** Tests java 8 java.time classes ability to use nanosecond times.
*
* Note that higher precision date times are referred to as "instants".
* http://docs.oracle.com/javase/8/docs/api/java/time/Instant.html
*
* "The range of an instant requires the storage of a number larger than a long.
* To achieve this, the class stores a long representing epoch-seconds and an
* int representing nanosecond-of-second, which will always be between 0 and
* 999,999,999. The epoch-seconds are measured from the standard Java epoch of
* 1970-01-01T00:00:00Z where instants after the epoch have positive values, and
* earlier instants have negative values. For both the epoch-second and
* nanosecond parts, a larger value is always later on the time-line than a
* smaller value.
* EPOCH Constant for the 1970-01-01T00:00:00Z epoch instant.
* The minimum supported Instant, '-1000000000-01-01T00:00Z'.
* The maximum supported Instant, '1000000000-12-31T23:59:59.999999999Z'.
* "
*
*
*/
public class NanoDateTest {
public static void main(String[] args) {
NanoDateTest myTest = new NanoDateTest();
myTest.run();
}
public void run() {
// There are 1000000000 nanos per second or 10000000 nano per .01 second
String testDate = "2012-11-30T21:45:13Z";
Instant startTime = Instant.parse(testDate);
System.out.println("Starting time: " + startTime.toString());
System.out.println("Compare start to start " + startTime.compareTo(startTime));
Instant tmpTime1 = startTime.plus(1L,NANOS); //add 1 Nanosecs
System.out.println("added 1 Nanos: " + tmpTime1.toString());
Instant tmpTime2 = tmpTime1.plus(1L,NANOS); //add 1 Nanosecs
System.out.println("added another 1 Nanos: " + tmpTime2.toString());
tmpTime2 = tmpTime1.plus(10000000L,NANOS); //add .01 seconds as Nanosecs
System.out.println("added 10 million Nanos: " + tmpTime2.toString());
tmpTime2 = tmpTime2.plus(10L,MILLIS); //add .01 second as Milliseconds
System.out.println("added another 10 Millis: " + tmpTime2.toString());
tmpTime2 = tmpTime2.plus(10L,SECONDS); //add 10 seconds as Seconds
System.out.println("added another 10 Seconds: " + tmpTime2.toString());
tmpTime2 = tmpTime2.plus(3L,MINUTES); //add 3 minutes as minutes
System.out.println("added another 3 minutes: " + tmpTime2.toString());
tmpTime2 = tmpTime2.plus(7L,HOURS); //add 7 hours as hours
System.out.println("A: added another 7 hours: " + tmpTime2.toString());
System.out.println("Compare start to A: " + startTime.compareTo(tmpTime2));
tmpTime2 = tmpTime2.plus(-2L,DAYS); //subtract 2 days as days
System.out.println("B: subtracted 2 days: " + tmpTime2.toString());
System.out.println("Compare start to B: " + startTime.compareTo(tmpTime2));
System.out.println("Compare start to start: " + startTime.compareTo(startTime));
Long difference = startTime.until(tmpTime2,NANOS);
System.out.println("Subtract start - B as NANOS: " + difference);
difference = startTime.until(tmpTime2,MILLIS);
System.out.println("Subtract start - B as MILLIS: " + difference);
difference = startTime.until(tmpTime2,SECONDS);
System.out.println("Subtract start - B as SECONDS: " + difference);
difference = startTime.until(tmpTime2,MINUTES);
System.out.println("Subtract start - B as MINUTES: " + difference);
difference = startTime.until(tmpTime2,HOURS);
System.out.println("Subtract start - B as HOURS: " + difference);
difference = startTime.until(tmpTime2,DAYS);
System.out.println("Subtract start - B as DAYS: " + difference);
Long samplingRate = 200L; //200 HZ = 1000000000 nanos per 200 samples
Long nanosPerSample = 1000000000/samplingRate;
System.out.println("\nsamplingRate: " + samplingRate + " Hz" );
System.out.println("nanosPerSample: " + nanosPerSample + "\n");
System.out.println("Starting time: " + startTime.toString());
//200 hz for an 8 second record = 1600 readings per record
Long entriesPerRecord = 1600L;
// We know this from reading the header
Long numberRecords = 4216L;
Instant endTime = startTime.plus(nanosPerSample * entriesPerRecord * numberRecords,NANOS);
System.out.println("Ending time: " + endTime.toString());
}
}
output:
Starting time: 2012-11-30T21:45:13Z
Compare start to start 0
added 1 Nanos: 2012-11-30T21:45:13.000000001Z
added another 1 Nanos: 2012-11-30T21:45:13.000000002Z
added 10 million Nanos: 2012-11-30T21:45:13.010000001Z
added another 10 Millis: 2012-11-30T21:45:13.020000001Z
added another 10 Seconds: 2012-11-30T21:45:23.020000001Z
added another 3 minutes: 2012-11-30T21:48:23.020000001Z
A: added another 7 hours: 2012-12-01T04:48:23.020000001Z
Compare start to A: -1
B: subtracted 2 days: 2012-11-29T04:48:23.020000001Z
Compare start to B: 1
Compare start to start: 0
Subtract start - B as NANOS: -147409979999999
Subtract start - B as MILLIS: -147409980
Subtract start - B as SECONDS: -147409
Subtract start - B as MINUTES: -2456
Subtract start - B as HOURS: -40
Subtract start - B as DAYS: -1
samplingRate: 200 Hz
nanosPerSample: 5000000
Starting time: 2012-11-30T21:45:13Z
Ending time: 2012-12-01T07:07:21Z
--------------------
Ok so I'm wondering why that entry B as MILLIS looks like it was rounded up whereas the next entry B as SECONDS looks like it was truncated? What is supposed to be going on here?
BTW why not have the ability to pass double arguments to these functions instead of longs? That would work a lot better for me. (I want fractional things so to speak).