4

I am trying to change from standard ISO 8601 format 2014-09-11T21:28:29.429209Z into a nice MMM d yyyy hh:mm z format, however my current code is failing.

public void setCreatedAt( String dateTime ) {

    LocalDate newDateTime = LocalDate.parse(dateTime);

    try {
        DateTimeFormatter format = DateTimeFormatter.ofPattern("MMM d yyyy hh:mm a z");
        createdAt = newDateTime.format(format); 
    }
    catch (Exception e) {
    }

}

I am receiving the time and date from an api.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Pocari
  • 43
  • 1
  • 4

3 Answers3

4

A java.time.LocalDate is "a date without a time-zone in the ISO-8601 calendar system, such as 2007-12-03" so there is not enough information there. Use java.time.ZonedDateTime instead.

Also, swallowing exceptions like that makes it much harder to troubleshoot. When you don't intend to handle an exception either don't catch it at all, catch and re-throw it wrapped in a RuntimeException or at the very least log it (e.printStackTrace() or similar) .

jakber
  • 3,549
  • 20
  • 20
  • it worked! Thank you! I definitely need to work on the exceptions. Thank you for the tip! :) – Pocari Jul 08 '15 at 17:50
  • 1
    Also note that `LocalDate` is not able to hold the time components, only the date components. – YoYo Jul 08 '15 at 17:50
3

tl;dr

Instant.parse( "2014-09-11T21:28:29.429209Z" )
       .atZone( ZoneId.of( "Asia/Kolkata" ) )
       .format( DateTimeFormatter.ofPattern("MMM d uuuu hh:mm a z" , Locale.US ) )

See this code run live at IdeOne.com.

Details

The Answer by Jakber will work technically but is misleading.

ZonedDateTime is for time zones

A ZonedDateTime is meant to have an assigned time zone such as America/Montreal or Pacific/Auckland.

But this input string lacks a time zone. The Z on the end is short for Zulu and means UTC, or in other words, an offset-from-UTC of zero hours, +00:00.

A time zone is a historical collection of offsets for a particular region with rules for upcoming changes to the offset for anomalies such as Daylight Saving Time (DST).

Instant

The input string is better parsed as an Instant which represents a moment on the timeline always in UTC. This class directly parses such strings in that particular standard ISO 8601 format, so no need for formatting pattern.

Instant instant = Instant.parse( "2014-09-11T21:28:29.429209Z" );

Adjust into time zone

You can adjust into a time zone to get a ZonedDateTime.

ZoneId z = ZoneId.of( "Asia/Kolkata" ) ;
ZonedDateTime zdt = instant.atZone( z );

Generating string

To generate a string in the same format as input, simply call Instant::toString().

String output = instant.toString() ;

For your custom format using the wall-clock time of a region, use DateTimeFormatter with your custom formatting pattern. And your ZonedDateTime. As a good habit, always specify the desired Locale used for the human language in translation and cultural norms in formatting.

DateTimeFormatter f = DateTimeFormatter.ofPattern("MMM d uuuu hh:mm a z" , Locale.US );
String output = zdt.format( f ); 

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
0
public void setCreatedAt(String dateTime) {
    SimpleDateFormat sdfSource = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.getDefault());
    SimpleDateFormat sdfTarget = new SimpleDateFormat("MMM d yyyy hh:mm a z", Locale.getDefault());
    try {
        Date date = sdfSource.parse(dateTime);
        String createdAt = sdfTarget.format(date);
        Log.e(TAG, "setCreatedAt: createdAt " + createdAt);
    } catch (ParseException e) {
        e.printStackTrace();
    }
}
Hasan El-Hefnawy
  • 1,249
  • 1
  • 14
  • 20
  • Please don’t teach the young ones to use the long outdated and notoriously troublesome `SimpleDateFormat` class. At least not as the first option. And not without any reservation. We have so much better in [`java.time`, the modern Java date and time API,](https://docs.oracle.com/javase/tutorial/datetime/) and its `DateTimeFormatter`. Which the OP is even already using. – Ole V.V. Dec 07 '22 at 06:37