1

I have a problem with parsing the following date from string: "1/29/2014 11:45:00 AM" I do it the following way:

String source = "1/29/2014 11:45:00 AM";
Date startDate;
String sdfPattern = "MM/dd/yyyy hh:mm:ss aa";
SimpleDateFormat sdf = new SimpleDateFormat(sdfPattern, Locale.getDefault());
sdf.setTimeZone(TimeZone.getTimeZone("Europe/London"));
this.startDate = sdf.parse(source);

Interestingly, this works fine in a java project, but not in android. The error message I get:

01-15 15:36:46.950: W/System.err(2713): java.text.ParseException: Unparseable date: "1/29/2014 11:45:00 AM" (at offset 19)

Can anybody tell me what I am doing wrong?

longwalker
  • 1,614
  • 2
  • 13
  • 18

3 Answers3

6

Your format string specifies that you'll provide a two-digit month, but you're only providing "1".

I suspect you want:

String sdfPattern = "M/d/yyyy hh:mm:ss aa";

Additionally, the "AM/PM" designator is locale-sensitive (as are the date and time separators) . If you know that it will always use English, you should say so:

SimpleDateFormat sdf = new SimpleDateFormat(sdfPattern, Locale.US);

Unless the data is actually entered by the user (or being formatted for the user) you should avoid Locale.getDefault().

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Though I agree with you , why this is not an issue in Java? – kosa Jan 15 '14 at 14:48
  • @Nambari: It could be a matter of it parsing leniently - or the locale issue raised in my edit. – Jon Skeet Jan 15 '14 at 14:49
  • 1
    I threw this in an android project and it worked w/o problems. I'm using API version 14 – d3n13d1 Jan 15 '14 at 14:54
  • I tried with a single M, and changed locale to US... it still does not work. I am guessing, "offset 19" is hinting on AM/PM. But I am not sure – longwalker Jan 15 '14 at 14:57
  • It was because of `Locale`, I changed the Locale to `Locale.US` but the rest remained the same. However, it was a little complicated in my code, that I used many of SimpleDateFormat's and it took some time for me to figure it out. Thanks for helping me out! – longwalker Jan 15 '14 at 15:17
1

Your default locale may not match the AM/PM marker in the input String causing the exception. Try using

SimpleDateFormat sdf = new SimpleDateFormat(sdfPattern, Locale.ENGLISH);
Reimeus
  • 158,255
  • 15
  • 216
  • 276
0

java.time

The Question and other Answers use the troublesome old legacy date-time classes bundled with the earliest versions of Java. Now supplanted by the java.time classes.

ISO 8601

By the way, use the ISO 8601 formats when generating Strings to represent date-time values for exchange with other software. Your format is ambiguous and trickier to parse, unlike the standard formats.

DateTimeFormatter

The codes defining a formatting pattern in java.time.DateTimeFormatter are similar to the outmoded SimpleDateFormat but not exactly. So read the doc carefully.

String input = "1/29/2014 11:45:00 AM";

Locale locale = Locale.ENGLISH;  // For translating the “AM” & “PM”.
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "M/d/uuuu hh:mm:ss a" ).withLocale( locale );

LocalDateTime

Your input lacks any indication of an offset-from-UTC or a time zone. So we parse as a LocalDateTime object.

LocalDateTime ldt = LocalDateTime.parse ( input , f );

ldt.toString(): 2014-01-29T11:45

A LocalDateTime object purposely lacks any offset-from-UTC or time zone. That means it does not represent a moment on the timeline, only a rough idea about possible moments. You must assign an offset or time zone to give it meaning.

OffsetDateTime

If the context of your suggestions indicates this input was meant to be in UTC, apply the constant ZoneOffset.UTC to get an OffsetDateTime.

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

odt.toString(): 2014-01-29T11:45Z

ZonedDateTime

On the other hand, if the context indicates a specific time zone, apply a ZoneId to get a ZonedDateTime. The Questions seems to indicate that the Europe/London time zone is intended. Be aware that this time zone is not the same as UTC.

ZoneId z = ZoneId.of ( "Europe/London" );
ZonedDateTime zdt = ldt.atZone ( z );

zdt.toString(): 2014-01-29T11:45-05:00[America/Montreal]

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP (see How to use…).

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.

Community
  • 1
  • 1
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154