Your analysis is correct. The pattern string is merely a shorthand suitable for compatibility with SimpleDateFormat. As you note, the 'Z' in the pattern doesn't permit parsing of the letter 'Z' as +00:00.
As you also note, this functionality is supported by the DateTimeFormatter class. I would comment that so long as the pattern is used to print the zone, then the parse will parse it back again (because it will use +00:00). Stephen James Abley wrote: > We are using joda-time 1.6 to persist a textual representation of a > date, like so: > > String dateText = > ISODateTimeFormat.basicDateTime().print(startDate.getTimeInMillis()); > > where startDate is a java.util.Calendar. > > So this is storing the string "20091030T100600.000Z", for example (the > application is running in GMT). > > Later on, that field is retrieved, and we are trying to read the String > back into a DateTime, then format for presentation on a web page. > > DateTimeFormatter formatter = > DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss.SSSZ"); // The pattern is > specified externally > String text = "20091030T100600.000Z"; // Read from persistent storage > really. > DateTime date = formatter.parseDateTime(text); > // ... then format the DateTime according to the client's preferred style... > > This fails with: > > java.lang.IllegalArgumentException: Invalid format: > "20091030T100600.000Z" is malformed at "Z" > at > org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:673) > > So I wrote some characterization tests to aid my understanding of the API. > > /** > * Passes. > * > * @throws Exception > */ > @Test > public void roundTrippingOfJodaTimeDates() throws Exception { > DateTimeFormatter formatter = ISODateTimeFormat.basicDateTime(); > > DateTime instant = new DateTime(2009, 10, 30, 10, 6, 0, 0); > String now = formatter.print(instant.getMillis()); > > assertEquals("20091030T100600.000Z", now); > > DateTime rehydrated = formatter.parseDateTime(now); > > assertEquals(instant, rehydrated); > } > > /** > * This test passes. > * > * @throws Exception > */ > @Test > public void > parsingDateTimeWithExplicitPatternAndLongFormOfTimezone() throws Exception { > DateTimeFormatter formatter = > DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss.SSSZ"); > String text = "20091030T100600.000+00:00"; > DateTime date = formatter.parseDateTime(text); > assertNotNull(date); > } > > /** > * This test fails, when attempting to parseDateTime. > * @throws Exception > */ > @Test > public void > parsingDateTimeWithExplicitPatternAndShortFormOfTimezone() throws > Exception { > DateTimeFormatter formatter = > DateTimeFormat.forPattern("yyyyMMdd'T'HHmmss.SSSZ"); > String text = "20091030T100600.000Z"; > DateTime date = formatter.parseDateTime(text); > assertNotNull(date); > } > > AFAICT, the difference is that the formatter created in > ISODateTimeFormat.basicDateTime() calls > DateTimeFormatterBuilder.appendTimeZoneOffset(String, boolean, int, int) > passing in "Z" as the zeroOffsetParameter, but when I call > DateTimeFormat.forPattern(String), null gets passed into the same API > method as the zeroOffsetText parameter. This test demonstrates that it > is possible to construct a DateTimeFormatter which will happily parse > the string, but I can't see a way of getting this without creating my > own code to parse a pattern and create a DateTimeFormatter, which I'd > like to avoid. > > /** > * This passes, but I'd have to create my own parser to do this, > which feels painful. > * > * @throws Exception > */ > @Test > public void > parsingDateTimeWithExplicitBuilderAndShortFormOfTimezone() throws > Exception { > DateTimeFormatter formatter = new DateTimeFormatterBuilder() > .appendYear(4, 4) > .appendMonthOfYear(2) > .appendDayOfMonth(2) > .appendLiteral('T') > .appendHourOfDay(2) > .appendMinuteOfHour(2) > .appendSecondOfMinute(2) > .appendLiteral('.') > .appendSecondOfDay(3) > .appendTimeZoneOffset("Z", false, 2, 2) > .toFormatter(); > String text = "20091030T100600.000Z"; > DateTime date = formatter.parseDateTime(text); > assertNotNull("Can cope with Z literal", date); > > text = "20091030T100600.000+00:00"; > date = formatter.parseDateTime(text); > assertNotNull("Can cope with offset", date); > } > > Can anyone point out what I'm doing wrong? Why can't I round-trip the > value in the way that I'm currently trying, using > DateTimeFormat.forPattern(String) or similar? > > Regards, > > James > > > ------------------------------------------------------------------------ > > ------------------------------------------------------------------------------ > Come build with us! The BlackBerry(R) Developer Conference in SF, CA > is the only developer event you need to attend this year. Jumpstart your > developing skills, take BlackBerry mobile applications to market and stay > ahead of the curve. Join us from November 9 - 12, 2009. Register now! > http://p.sf.net/sfu/devconference > > > ------------------------------------------------------------------------ > > _______________________________________________ > Joda-interest mailing list > Joda-interest@lists.sourceforge.net > https://lists.sourceforge.net/lists/listinfo/joda-interest ------------------------------------------------------------------------------ Let Crystal Reports handle the reporting - Free Crystal Reports 2008 30-Day trial. Simplify your report design, integration and deployment - and focus on what you do best, core application coding. Discover what's new with Crystal Reports now. http://p.sf.net/sfu/bobj-july _______________________________________________ Joda-interest mailing list Joda-interest@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/joda-interest