2

Using Java's SimpleDateFormat and Google's Gson library, I'm trying to parse the date from a Json file downloaded from the Minecraft library directory. There appears to be an issue when parsing the date using the following SimpleDateFormat: yyyy-MM-dd'T'HH:mm:ssZ

I've also tried the following:

yyyy-MM-dd'T'HH:mm:ssX
yyyy-MM-dd'T'HH:mm:ssz
yyyy-MM-dd'T'HH:mm:ssx

Since the file is actually downloaded from the web, I have no means of changing it. So the solution must lie within altering my code to either not include the date, or removing the problematic code from my source. This happens to be quite a problem, since my application dies when the date is parsed, and appears to be a parsing issue, rather than a problem with the file.

The date formats are as follows:

2013-12-18T00:41:38-0500
2013-10-25T15:00:00+02:00

Both of the above dates crash it. And both of them come from separate files. I've browsed the web for multiple solutions and none of them seem to fix it.

I've even asked on the #technic channel and browsed the TechnicLauncher source code, and found pretty much nothing to help. And since the class I'm using is actually the exact same as the Technic Launcher, it's perplexing me. If you'd like to peruse the source code, you can take a look here: GitHub :: LauncherCore

LeoV117
  • 114
  • 12

3 Answers3

0

Java 7 - use the format code X

import java.text.SimpleDateFormat;

public class Test {
  public static void main(String[] args) {
    SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssX");
    String date1 = "2013-12-18T00:41:38-0500";
    String date2 = "2013-10-25T15:00:00+08:00";

    try {
      System.out.println(dateFormat.parse(date1));      
      System.out.println(dateFormat.parse(date2));
    } catch (Exception e ) {
      System.out.println(e);
    }     
  }
}

produces the output

Wed Dec 18 05:41:38 GMT 2013
Fri Oct 25 08:00:00 BST 2013

When run in Ireland in winter.

Paul Smith
  • 454
  • 6
  • 11
  • 1
    `2013-12-18T00:41:38-0500` is not the same as `Wed Dec 18 00:41:38 GMT 2013` because the timezone is GMT. Wouldn't it be `Wed Dec 18 05:41:38 GMT 2013`. Removing the 'Z' just ignores the timezone, and assumes the JVM's default timezone – Tom Feb 27 '14 at 00:39
  • This only helped me find whether the format was operating correctly, It didn't actually assist with my problem. – LeoV117 Feb 27 '14 at 22:38
  • You stated that your problem was that it crashed when you used the 'Z' suffix. The solution I proposed was to use the 'X' suffix instead which a) does not crash and b) gives the correct results. – Paul Smith Mar 12 '14 at 16:55
0

Java date/time is a major piece of headaches. Anyway, the trick is that I used, and seem to work, both xml calendar parser combine with SimpleDateFormat. I also posted this a while back on my blog: a simple trick for date format and may be something there you can use too. But anyway, here is the answer. Simply take this method and make a few small tweet and plug in (replace) the deserializeToDate() method on that DateTypeAdapter class:

   private Date deserializeToDate(/*JsonElement*/String json) /*Json*/ParseException {
      Date d = null;
      String date = json; // json.getAsString();
      try {
         d = javax.xml.bind.DatatypeConverter.parseDateTime(date).getTime();
      } catch (Exception e) {} // ignore
      if (d == null) {
         SimpleDateFormat dateFormat = 
                  new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
         d = dateFormat.parse(date);      
      }
      return d;
   }

   @Test
   public void shouldParseXmlDateTime() {
      String date1 = "2013-12-18T00:41:38-0500";
      String date2 = "2013-10-25T15:00:00+08:00";

      try {
        System.out.println(deserializeToDate(date1));      
      } catch (Exception e ) {
        System.out.println(e);
      }     
      try {
         System.out.println(parse(date2));      
       } catch (Exception e ) {
         System.out.println(e);
       }     
   }

and this should produce:

Wed Dec 18 00:41:38 EST 2013
Fri Oct 25 03:00:00 EDT 2013
TA Nguyen
  • 453
  • 1
  • 3
  • 8
  • Aspirin for that headache: [Joda-Time](http://www.joda.org/joda-time/) or [java.time](http://download.java.net/jdk8/docs/api/java/time/package-summary.html). – Basil Bourque Feb 27 '14 at 10:03
  • As much as this is useful to others, this doesn't solve my problem. The issue I'm having is that the date that I retreive from my file causes a JsonParseException when run. – LeoV117 Feb 27 '14 at 22:40
  • I see where you are going with this, you want me to fix the LauncherCore ... Anyway, you can do it too... All you have to do is: download the LauncherCore, make some change and repackage it. The change change you need to make is in the DateTypeAdapter.deserializeToDate()? Simply replace with the method I changed above. – TA Nguyen Feb 28 '14 at 01:41
  • I'm afraid I don't quite understand what it is that I'm supposed to fix. – LeoV117 Feb 28 '14 at 18:32
  • Yeah, I'm afraid that this doesn't actually change anything. I get the exact same result: `Exception: JsonSyntaxException, Message: 2013-10-25T15:00:00+02:00` – LeoV117 Feb 28 '14 at 18:37
  • can you share with me what you done with the DateTypeAdapter? – TA Nguyen Feb 28 '14 at 19:14
0

tl;dr

Until bug is fixed:

OffsetDateTime.parse( 
    "2013-12-18T00:41:38-0500" , 
    DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" )
)

When bug is fixed:

OffsetDateTime.parse( "2013-12-18T00:41:38-0500" )

java.time

The modern approach uses the java.time classes.

OffsetDateTime odt = OffsetDateTime.parse( "2013-10-25T15:00:00+02:00" ) ;

That should also work for 2013-12-18T00:41:38-0500. Unfortunately, it does not. The OffsetDateTime class has a bug that bites when the offset-from-UTC portion lacks the optional colon between hours and minutes. So 2013-12-18T00:41:38-05:00 would work, but not 2013-12-18T00:41:38-0500.

As a workaround, define a formatting pattern.

String input = "2013-12-18T00:41:38-0500" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuu-MM-dd'T'HH:mm:ssX" ) ;
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;

odt.toString(): 2013-12-18T00:41:38-05:00

For more discussion, see similar Questions:


Joda-Time

UPDATE: the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. This section left intact as history.

FYI, if you used Joda-Time instead of the notoriously troublesome java.util.Date/Calendar classes, you could simply pass that ISO 8601 string straight into a DateTime constructor without the bother of a formatter. Joda-Time uses ISO 8601 as its defaults.

DateTimeZone timeZone = DateTimeZone.forID( "America/Montreal" );
DateTime dateTime = new DateTime( "2007-03-01T13:00:00Z", timeZone );

If you want to work in UTC without adjusting to a time zone, just omit the timeZone stuff from code above.

If you need a java.util.Date object for other purposes, convert from Joda-Time.

java.util.Date date = dateTime.toDate();

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.

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