0

I want to create a java.util.Date object from microseconds. But i don't want to lose its precision microseconds to millisecond. Currently i am converting microseconds to Date object in the following way. If i pass microseconds to the Date constructor then it gives a wrong date like 56521-12-01.

long microSeconds = value.getTimestampValue();// This function returns a microseconds.
DateFormat FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSSSSS);
long millis = TimeUnit.MILLISECONDS.convert(microSeconds, TimeUnit.MICROSECONDS);
String startDate = FORMAT.format(new Date(millis));

I don't want to convert microseconds to milliseconds. Is there is a method of API or java-8 utility where i can direct convert the microseconds to Date object?

The problem with this method is It remove the last three digits of microseconds to make it milliseconds then create a date object from milliseconds and parser just multiply its milliseconds part with 1000 to convert it into microseconds. In this way i lost a actul microsends.

Khalid Shah
  • 3,132
  • 3
  • 20
  • 39
  • 9
    Your first mistake was attempting to use java.util.Date in Java 8. – Michael Jan 07 '20 at 16:45
  • I searched for the solution but i can't find the exact solution. So, I use a Date object. Could you tell me the solution – Khalid Shah Jan 07 '20 at 16:48
  • 4
    LocalDateTime could be a valid alternative. Could it be suitable for your purpose? – AM13 Jan 07 '20 at 16:48
  • This question is related to https://stackoverflow.com/a/1712215/274340 – onof Jan 07 '20 at 16:52
  • @AM13 yes i can use LocalDateTime. Can you give a solution in answer ? – Khalid Shah Jan 07 '20 at 16:52
  • 2
    I recommend you don’t use `SimpleDateFormat` and `Date`. Those classes are poorly designed and long outdated, the former in particular notoriously troublesome. Instead use `Instant`, `DateTimeFormatter` and other classes from [java.time, the modern Java date and time API](https://docs.oracle.com/javase/tutorial/datetime/). – Ole V.V. Jan 07 '20 at 19:59
  • 1
    Does this answer your question? [Create Java DateTime Instant from microseconds](https://stackoverflow.com/questions/57411881/create-java-datetime-instant-from-microseconds) And/or this? [Convert timestamp long to normal date format](https://stackoverflow.com/questions/6782185/convert-timestamp-long-to-normal-date-format) – Ole V.V. Jan 07 '20 at 20:00
  • 1
    Show sample data. – Basil Bourque Jan 07 '20 at 23:06

5 Answers5

7

tl;dr

Instant                                                  // Represent a moment as a count since the epoch reference of 1970-01-01T00:00Z.
.ofEpochSecond(                                          // Instantiate a `Instant` as a count of whole seconds plus fractional second.
    TimeUnit.MICROSECONDS.toSeconds( microseconds ) ,    // Count of whole seconds since the epoch reference.
    TimeUnit.MICROSECONDS.toNanos( microseconds )        // Calculate fractional second as a count of nanoseconds.
    - 
    TimeUnit.SECONDS.toNanos( 
        TimeUnit.MICROSECONDS.toSeconds( microseconds )
    ) 
)                                                        // Returns an `Instant`.
.toString()                                              // Generate text in standard ISO 8601 format.
.replace( "T" , " " )                                    // Replace a `T` with a SPACE for desired output format.
.replace( "Z" , "" )                                     // Remove the `Z` from the end, that indicates the date and time is in the context of UTC.   

Avoid legacy date-time classes

You are using terrible date-time classes that were supplanted years ago by the modern java.time classes defined in JSR 310.

Furthermore, as others indicated, the legacy classes cannot accommodate microseconds, only milliseconds. Well, actually, the legacy class java.sql.Timestamp attempts to represent nanoseconds, but does so by way of a terrible hack that includes a fractional second in milliseconds and a fractional second of nanoseconds (a real mess).

java.time

Table of date-time types in Java, both modern and legacy

Sample data

For a demo, let's create the sample number of microseconds since the first moment of 1970 in UTC.

// Convert to microseconds. Use as input value to further code below.
Instant instantPrime = Instant.now().truncatedTo( ChronoUnit.MICROS ); // Drop any nanoseconds, to keep only microseconds.
long wholeSecondsPrime = instantPrime.getEpochSecond();
long nanoAdjustmentPrime = instantPrime.getNano();
long microseconds = 
    TimeUnit.SECONDS.toMicros( wholeSecondsPrime ) + 
    TimeUnit.NANOSECONDS.toMicros( nanoAdjustmentPrime )
;

Processing

Let's chop that count of microseconds into two parts, a number of whole seconds since 1970-01-01T00:00Z, and a fractional second as a number of microseconds.

// Convert from microseconds.
long wholeSeconds = TimeUnit.MICROSECONDS.toSeconds( microseconds );
long nanoAdjustment = TimeUnit.MICROSECONDS.toNanos( microseconds ) - TimeUnit.SECONDS.toNanos( wholeSeconds );

Put them back together again.

Instant instant = Instant.ofEpochSecond( wholeSeconds , nanoAdjustment );
boolean match = instant.equals( instantPrime );

Dump to console.

System.out.println( "instantPrime = " + instantPrime );
System.out.println( "wholeSecondsPrime = " + wholeSecondsPrime );
System.out.println( "nanoAdjustmentPrime = " + nanoAdjustmentPrime );

System.out.println( "microseconds = " + microseconds );

System.out.println( "wholeSeconds = " + wholeSeconds );
System.out.println( "nanoAdjustment = " + nanoAdjustment );
System.out.println( "instant = " + instant );

System.out.println( "match = " + match );

instantPrime = 2020-01-07T23:32:26.385565Z

wholeSecondsPrime = 1578439946

nanoAdjustmentPrime = 385565000

microseconds = 1578439946385565

wholeSeconds = 1578439946

nanoAdjustment = 385565000

instant = 2020-01-07T23:32:26.385565Z

match = true

Strings

Generate text representing the value of your Instant using standard ISO 8601 format.

String output = instant.toString() ;

2020-01-07T23:32:26.385565Z

Your desired format is close to that. Replace the T with a SPACE. And remove the Z, though be careful about that. Presenting date-time as text without indicating the time zone or offset-from-UTC can create ambiguity and confusing for the reader. I would recommend including the Z.

String output = instant.toString().replace( "T" , " " ).replace( "Z" , "" ) ;

2020-01-07 23:32:26.385565


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.

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thank you so much @Basil for insight details :) – Khalid Shah Jan 08 '20 at 05:12
  • I execute the same above code on my machine but it will print time differently. `instantPrime = 2020-01-08T11:29:19.065Z wholeSecondsPrime = 1578482959 nanoAdjustmentPrime = 65000000 microseconds = 1578482959065000 wholeSeconds = 1578482959 nanoAdjustment = 65000000 instant = 2020-01-08T11:29:19.065Z match = true` It only shows the time in milliseconds. – Khalid Shah Jan 08 '20 at 11:33
  • @KhalidShah Are you running Java 8? That version used an implementation of [`Clock`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/time/Clock.html) that captured the current moment in milliseconds. Some implementations of Java 9 and later uses a new `Clock` that captures the current moment in microseconds. The *java.time* classes can represent nanoseconds, but conventional computer hardware clocks are not that accurate. – Basil Bourque Jan 08 '20 at 17:18
  • Yes i am using java 8 – Khalid Shah Jan 08 '20 at 17:19
6

You won't be able to do this using java.util.Date. From the API:

The class Date represents a specific instant in time, with millisecond precision.

jsheeran
  • 2,912
  • 2
  • 17
  • 32
  • My use case is only convert microseconds to` string representation of actual time` with microseconds precision. I can use other classes instead of Date. – Khalid Shah Jan 07 '20 at 16:51
  • 1
    @KhalidShah Then you should **edit** the question and say that. – Andreas Jan 07 '20 at 17:33
4
int seconds = (int) (microSeconds / 1_000_000);
int nanoSeconds = ((int) (microSeconds % 1_000_000)) * 1_000;
LocalDateTime t = LocalDateTime.ofEpochSecond(seconds, nanoSeconds, ZoneOffset.UTC);

String s = t.toString(); // with a T
s = t.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME); // with a T
s = t.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS"));

Date has a milliseconds resolution. And the new time classes are far better, though need a bit more effort.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
1

If your string contains milliseconds, then firstly we need to choose the appropriate pattern for it.

String date = "2021-11-15T07:45:28.655";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
LocalDate dt = LocalDate.parse(date, formattter);

It resolves your problem.

If it includes time zone as well, then you need to change the pattern again.

String date = "2021-11-15T07:45:28.655-08:00";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSz");
LocalDate dd = LocalDate.parse(date, formatter);
Suraj Rao
  • 29,388
  • 11
  • 94
  • 103
Swathi Jak
  • 21
  • 3
0

Just an alternative using LocalDateTime:

LocalDateTime date =
LocalDateTime.ofInstant(Instant.ofEpochMilli(millis), ZoneId.systemDefault());

However If you just want a sort of "well formatted timestamp" you can use just:

LocalDateTime.now()
AM13
  • 661
  • 1
  • 8
  • 18