Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Converting string to Instant

I am trying to covert datetime in string to instant using java 8 or utils package.

For eg.

String requestTime = "04:30 PM, Sat 5/12/2018"; 

to

Instant reqInstant should result in 2018-05-12T20:30:00.000Z 

reqString is in America/Toronto timezone.

This is what I tried

 String strReqDelTime = "04:30 PM, Sat 5/12/2018";  Date date = new SimpleDateFormat("hh:mm a, EEE MM/dd/yyyy").parse(requestTime);  Instant reqInstant = date.toInstant(); 

The above code results in "2018-05-12T23:30:00Z".

Any help is appreciated.

like image 667
Venky Avatar asked May 11 '18 20:05

Venky


People also ask

How do I convert a string to an instant in Java?

The parse() method of Instant class help to get an instance of Instant from a string value passed as parameter. This string is an instant in the UTC time zone. It is parsed using DateTimeFormatter.

How do you convert instant to string?

The toString() method of Instant class returns string representation of this instant using ISO-8601 representation and format used is the same as DateTimeFormatter. ISO_INSTANT. Returns: This method returns an ISO-8601 representation of this instant, not null.

Is Instant immutable?

Implementation Requirements: This class is immutable and thread-safe.


1 Answers

tl;dr

  • Fix your formatting pattern for unpadded month & day.
  • Use only java.time classes, never the legacy classes.

Contrived example:

LocalDateTime.parse(                   // Parse as an indeterminate `LocalDate`, devoid of time zone or offset-from-UTC. NOT a moment, NOT a point on the timeline.     "04:30 PM, Sat 5/12/2018" ,        // This input uses a poor choice of format. Whenever possible, use standard ISO 8601 formats when exchanging date-time values as text. Conveniently, the java.time classes use the standard formats by default when parsing/generating strings.     DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US )  // Use single-character `M` & `d` when the number lacks a leading padded zero for single-digit values. )                                      // Returns a `LocalDateTime` object. .atZone(                               // Apply a zone to that unzoned `LocalDateTime`, giving it meaning, determining a point on the timeline.     ZoneId.of( "America/Toronto" )     // Always specify a proper time zone with `Contintent/Region` format, never a 3-4 letter pseudo-zone such as `PST`, `CST`, or `IST`.  )                                      // Returns a `ZonedDateTime`. `toString` → 2018-05-12T16:30-04:00[America/Toronto]. .toInstant()                           // Extract a `Instant` object, always in UTC by definition. .toString()                            // Generate a String in standard ISO 8601 format representing the value within this `Instant` object. Note that this string is *generated*, not *contained*. 

2018-05-12T20:30:00Z

Use single-digit formatting pattern

You used MM in your formatting pattern, to mean any single-digit value (months January-September) will appear with a padded leading zero.

But your input lacks that padded leading zero. So use a single M.

Ditto for day-of-month I expect: d rather than dd.

Use only java.time

You are using troublesome flawed old date-time classes (Date & SimpleDateFormat) that were supplanted years ago by the java.time classes. The new classes entirely supplant the old. No need to mix the legacy and modern.

LocalDateTime

Parse as a LocalDateTime because your input string lacks any indicator of time zone or offset-from-UTC. Such a value is not a moment, is not a point on the timeline. It is only a set of potential moments along a range of about 26-27 hours.

String input = "04:30 PM, Sat 5/12/2018"; DateTimeFormatter f = DateTimeFormatter.ofPattern( "hh:mm a, EEE M/d/uuuu" , Locale.US );  // Specify locale to determine human language and cultural norms used in translating that input string. LocalDateTime ldt = LocalDateTime.parse( input , f ); 

ldt.toString(): 2018-05-12T16:30

ZonedDateTime

If you know for certain that input was intended to represent a moment using the wall-clock time used by the people of the Toronto Canada region, apply a ZoneId to get a ZonedDateTime object.

Assigning a time zone gives meaning to your unzoned LocalDateTime. Now we have a moment, a point on the timeline.

ZoneId z = ZoneId.of( "America/Toronto" ) ; ZonedDateTime zdt = ldt.atZone( z ) ;  // Give meaning to that `LocalDateTime` by assigning the context of a particular time zone. Now we have a moment, a point on the timeline. 

zdt.toString(): 2018-05-12T16:30-04:00[America/Toronto]

Instant

To see that same moment as UTC, extract an Instant. Same moment, different wall-clock time.

Instant instant = zdt.toInstant() ; 

instant.toString(): 2018-05-12T20:30:00Z


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?

  • Java SE 8, Java SE 9, Java SE 10, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

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.

like image 182
Basil Bourque Avatar answered Oct 21 '22 05:10

Basil Bourque