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
> [email protected]
> 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/joda-interest