1

I have a date value in Central Time

String cstDate = "02-JAN-19 03.34.33.540260000 AM";

I have to convert above string value to UTC format. I am using Java 1.8 and used ZonedDateTime.

Please find below code.

String DATE_FORMAT = "dd-MMM-yy hh.mm.ss.SSSSSSSSS a";      
String cstDate =  "02-JAN-19 03.34.33.540260000 AM";
LocalDateTime ldt = LocalDateTime.parse(cstDate,DateTimeFormatter.ofPattern(DATE_FORMAT));
ZonedDateTime utcDateTime = ldt.atZone(ZoneId.of("UTC"));        //CST+6
System.out.println("cst : " + cstDate);
System.out.println("utc : " + utcDateTime);

But getting an exception : Text '02-JAN-19 03.34.33.540260000 AM' could not be parsed at index 3

Not understanding why I am getting this exception.

Thanks

Surya Joseph
  • 15
  • 1
  • 5
  • Possible duplicate of [How to parse case-insensitive strings with jsr310 DateTimeFormatter?](https://stackoverflow.com/questions/10797808/how-to-parse-case-insensitive-strings-with-jsr310-datetimeformatter) – Joe C Jan 23 '19 at 22:17

1 Answers1

1

tl;dr

Your JAN value is not properly localized to English, so we must parse using a more customized DateTimeFormatter object produced via the builder pattern using the DateTimeFormatterBuilder class to parse without case-sensitivity.

UTC

UTC is not a “format”. UTC is the baseline against which we measure time zones around the globe. All time zones are some number of hours-minutes-seconds ahead or behind UTC. Time zones east of the demarcation point at the Royal Observatory, Greenwich are ahead of UTC, and those to the west are behind. An offset of zero is UTC itself.

LocalDateTime

Your input string lacks an indicator of time zone or offset-from-UTC. This is bad practice, as the value is ambiguous. Without zone or offset, we must parse as a LocalDateTime object.

We specify a formatting pattern to match your input. By the way, your choice of an input string format is less than optimal. Whenever possible, use the standard ISO 8601 formats.

DateTimeFormatterBuilder

Your input value of JAN is incorrect localization for the US and UK and likely others. So we cannot depend on the usual parsing. We must indicate parsing with case-insensitivity. To do so, we must build up a DateTimeFormatter object by using the DateTimeFormatterBuilder class.

String input = "02-JAN-19 03.34.33.540260000 AM" ;

DateTimeFormatterBuilder builder = 
    new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .appendPattern(
        "dd-MMM-uu hh.mm.ss.SSSSSSSSS a"
    ) ;
DateTimeFormatter f = builder.toFormatter( Locale.US ) ;
LocalDateTime ldt = LocalDateTime.parse( input , f ) ;

ldt.toString(): 2019-01-02T03:34:33.540260

Lacking any concept of time zone or offset-from-UTC means our LocalDateTime is not a moment, is not a point on the timeline. It represents potential moments along a range of 26-27 hours (the range of time zones around the globe). To determine a moment, we must assign an offset or zone.

ZonedDateTime

You claim to know that this input string was meant to represent a moment in CST. Unfortunately, CST is not a real time zone. Never use these 2-4 character pseudo-zones, as they are not standardized — they are not even unique! Did you mean China Standard Time? Maybe Central Standard Time in the Americas?

Real time zones have a name in Continent/Region format. I will guess that you meant a time zone such as America/Chicago. You have comment mentioning an offset of +6… did you mean -06:00 as used by America/Chicago in the winter?

ZoneId z = ZoneId.of( "America/Chicago" ) ;

Apply this time zone to our LocalDateTime to get a ZonedDateTime representing an actual moment.

ZonedDateTime zdt = ldt.atZone( z ) ;

zdt.toString(): 2019-01-02T03:34:33.540260-06:00[America/Chicago]

To see that same moment as UTC, extract an Instant. An Instant represents a moment in UTC, always in UTC.

Instant instant = zdt.toInstant() ;

instant.toString(): 2019-01-02T09:34:33.540260Z

See this code run live at IdeOne.com.

OffsetDateTime

Your Question was not clear. If you meant the input string is known to represent a moment in UTC, parse as a OffsetDateTime.

OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

Adjust into America/Chicago time zone. Same moment, different wall-clock time.

ZonedDateTime zdt = odt.atZoneSameInstant( 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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Thanks for the detailed explanation. It resolved my issue to a certain extent.CST I meant Central Standard Time. Now I am getting output in below format. Input String[CST] : "02-JAN-19 03.34.33.540260000 AM" Output String[UTC] ":2019-01-02T09:34:33.540260Z" But I need output in below format : "2019-01-02 09:34:33" – Surya Joseph Jan 24 '19 at 16:21
  • 1
    @SuryaJoseph Search for the `DateTimeFormatter` class and its `ofPattern` method. This has been covered many many many times already on Stack Overflow. – Basil Bourque Jan 24 '19 at 19:01
  • Thanks for the response.I am not able to use DateTimeFormatter and ofPattern due to incompatible types. – Surya Joseph Jan 24 '19 at 21:00