4

Can I use a java long to store with reasonable precision the epoch time in microseconds with out any special signed to unsigned conversion tricks? If so how would I calculate the end date range?

This is the usual 8 byte date range: -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

UPDATE

From suggestions to use:

new Date(Long.MAX_VALUE)

here is the end date for um:

new Date(Long.MAX_VALUE/1_000)

Sat Jan 09 20:00:54 PST 294247

And this is the end date using positive long values for nano seconds:

new Date(Long.MAX_VALUE/1_000_000)

Fri Apr 11 16:47:16 PDT 2262
simgineer
  • 1,754
  • 2
  • 22
  • 49
  • 1
    So what are you asking about **micro** or **nano** seconds? – PM 77-1 Feb 01 '19 at 00:21
  • 3
    https://stackoverflow.com/a/1743994/2970947 Is the answer for milliseconds. Divide the result of that by 1000000 to get the number for nanoseconds. `System.out.println(new Date(Long.MAX_VALUE / 1000000L));` – Elliott Frisch Feb 01 '19 at 00:21
  • @ElliottFrisch why is it divide by 1000000 and not 1000? I though milliseconds and nanoseconds only differ by a factor of 1000 and the java Date() class would take in milliseconds. – simgineer Feb 01 '19 at 00:29
  • Google: "nanoseconds per millisecond", Answer: "multiply the time value by 1e+6" – Elliott Frisch Feb 01 '19 at 00:30
  • 1
    Sorry for the confusion, I was just asking for microseconds. I said nano seconds accidentally. – simgineer Feb 01 '19 at 00:31
  • 2
    It will be working fine until Friday, April 11, 2262 11:47:16.854 PM – Ismail Sabry Feb 01 '19 at 00:36

1 Answers1

13

tl;dr

  • Nanos give only 3 centuries.
  • Never roll-your-own time-keeping. ☛ Use java.time
  • When exchanging date-time values, never use a count-from-epoch, use text in standard ISO 8601 format.

Doing the math

You must pick an epoch reference date. While dozens of various epochs are used in the industry, one of the more common is often referred to as Unix Time: The first moment of 1970 in UTC, 1970-01-01T00:00:00Z. Moments after that point are tracked using a positive number count, and prior moments use a negative number count.

Of course the length of a year varies by Leap Year, but we can easily approximate. Get the number of nanoseconds in a year using the TimeUnit class with its handy conversion methods.

Crunch some numbers.

long nanosPerDay = TimeUnit.DAYS.toNanos( 1L );
long nanosPerYear = ( long ) ( nanosPerDay * 365.25 );
long maximumYears = ( Long.MAX_VALUE / nanosPerYear );

Dump to console.

System.out.println( "nanosPerDay: " + nanosPerDay );
System.out.println( "nanosPerYear: " + nanosPerYear );
System.out.println( "Long.MAX_VALUE: " + Long.MAX_VALUE + " provides for maximumYears: " + maximumYears );

See this code run live at IdeOne.com.

nanosPerDay: 86400000000000

nanosPerYear: 31557600000000000

Long.MAX_VALUE: 9223372036854775807 provides for maximumYears: 292

So we get less than ±3 centuries before and after 1970. So this approach does work, if a few centuries is good enough for your app. At least you won’t be around to fix it when the calendar runs out. ;-)

Instant

Fortunately we need not do this math ourselves.

Modern Java happens to come with the most advanced date-time handling framework available for business-oriented apps: The java.time classes defined in JSR 310.

The java.time.Instant class uses a different strategy to tracking time. That class keeps a count of whole seconds before/after the epoch of 1970 UTC, plus a separate count of nanoseconds for the fractional-second of the moment.

Think of it as:

moment = ( whole-seconds + fractional-second ) ; // Since 1970-01-01T00:00:00Z.

This enables a minimum/maximum of:

Notice that java.time classes do carry a resolution of nanoseconds, while the legacy classes they supplanted (Date, Calendar, etc.) resolved to milliseconds.

For the gnarly details, see the class JavaDoc and the OpenJDK source code (in Mercurial).

Tip: The java.time classes are most appropriate to business-oriented purposes. If you are doing scientific, engineering, archeology, or history work, use other notations appropriate to the field, likely as String type.

Granularity

Be aware that different computer systems use different granularities in their time-keeping.

As noted above, the java.time classes resolve to nanoseconds, for nine digits of a decimal fractional second. The legacy classes used milliseconds, for three digits of a decimal fractional second. Other systems, such as the Postgres database, use microseconds for six digits of a decimal fractional second. When exchanging or comparing data across sytems, you may want to use the truncatedTo methods on various java.time classes.

Current conventional computer hardware clocks are accurate only to microseconds or grosser. They may report on nanoseconds but are not accurate to that degree. So, you will find that the Instant.now() method in Java 9, 10, & 11 capture the current moment to the microsecond (while the data type can handle nanos, it detects the current time in micros).

Instant.now().toString(): 2019-01-23T12:34:56.123456Z


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes. Hibernate 5 & JPA 2.2 support java.time.

Where to obtain the java.time classes?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154