Convert microseconds to milliseconds without loss of precision and format as date-time in Java

2.1k views Asked by At

How can I convert incoming long time value in microseconds into milliseconds and then format that to data time stamp as below:

yyyyMMdd-HH:mm:ss.SSS

I am using Java SimpleDateFormat to format the long value to the timestamp. But, converting the microseconds to milliseconds seems problem as I am loosing the value.

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HH:mm:ss.SSS");

To convert microsecond to millisecond, I am using the TimeUnit:

long micro //microseconds
long milli = TimeUnit.MILLISECONDS.convert(micro, TimeUnit.MICROSECONDS);

What is the right way to convert the value without loosing any data?

1

There are 1 answers

0
Basil Bourque On

I am using java SimpleDateFormat

Don’t.

Avoid the treacherous old date-time classes bundled with the earliest versions of Java. They were supplanted years ago with the java.time classes when JSR 310 was adopted.

convert incoming long time value in microseconds into milliseconds

Don’t.

The java.time classes use a resolution of nanoseconds, finer than your microseconds. So no need to throw away data.

Instant = ( whole seconds + fractional second as nanos )

Extract the number of whole seconds.

long seconds = TimeUnit.MICROSECONDS.toSeconds( micros ) ;

Get the fractional second, the amount of micros left over after subtracting for the whole seconds.

long microsRemaining = 
    micros 
    -
    TimeUnit.SECONDS.toMicros( seconds ) 
;

Convert the remaining micros to nanos, because the Instant class we use next represents a count of whole seconds plus a count of nanoseconds (for the fractional second).

long nanos = TimeUnit.MICROSECONDS.toNanos( microsRemaining ) ;

Combine the whole seconds with the fractional second in nanos. The Instant class represents a moment in UTC as a count since the epoch reference of first moment of 1970 in UTC, 1970-01-01T00:00Z.

Instant instant = Instant.ofEpochSecond( seconds ).plusNanos( nanos ) ;

To generate a string in standard ISO 8601 format, simply call toString.

String output = instant.toString() ;

The Z on the end of the string means UTC (an offset-from-UTC of zero hours-minutes-seconds), and is pronounced Zulu.

You can produce strings in your own custom formats using the DateTimeFormatter class. Search Stack Overflow as this has been covered many many many times already.

Tip: Your desired format is so close to the ISO 8601 format, YYYY-MM-DDTHH:MM:SSZ, that I strongly suggest using the standard format rather than make up your own cousin of that.

If you wish to see this same moment through the lens of the wall-clock time used by people of a certain region (a time zone), apply a ZoneId to get a ZonedDateTime.

ZoneId z = ZoneId.of( "Africa/Tunisia" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;

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.

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

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

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.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.