0

I am getting time and the timezone of the time separately from a external component. The time is in the format 'MMM dd yyyy hh:mma'. Ex: Oct 31 2014 12:54PM and the timezone of this time is received separately.

I need to normalize this time to EST timezone before saving in the database. I tried Calendar(I don't think this can be done with java Date), but there were considerable inconsistencies with the output, and then after some googling, thought Joda had better support and switched to it. But I am getting the below exception.

    String clientTimeZone = "America/New_York";
    String value = "Nov 25 2014  2:18PM";
     DateTimeFormatter df = DateTimeFormat.forPattern("MMM dd yyyy hh:mma");//.withLocale(Locale.ENGLISH);
            DateTime temp = df.withZone(DateTimeZone.forID(clientTimeZone)).withOffsetParsed().parseDateTime(value);
            DateTime date = temp.withZone(DateTimeZone.forID("America/New_York"));
            Timestamp ts = new Timestamp(date.getMillis());
            Date d = new Date(ts.getTime());
            System.out.println(d.toString());

I got:

java.lang.IllegalArgumentException: Invalid format: "Nov 25 2014 2:18PM" is malformed at " 2:18PM" at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:899) at LearnJoda.main(LearnJoda.java:34)

Any idea on what could be the issue?

kiran
  • 2,280
  • 2
  • 23
  • 30
  • Possible duplicate of: [link](http://stackoverflow.com/questions/7695859/how-to-convert-a-data-from-1-timezone-to-another-timezone) – dehlen Dec 29 '14 at 14:56
  • I created a test case of this and it seems to work. Check out http://hastebin.com/okeqotojip.avrasm - no exceptions. Or, is there something that is missing from the code? – wassgren Dec 29 '14 at 15:26
  • @wassgren I just updated the code example I am using. And I think I figured it out. The external system is sending ' 2' instead of '2' in hours. So it is creating an extra space which seems to be causing the issue. If I remove the extra space, the the exception is gone. Is there any way to handle this automatically. I wish I could ask the external system to handle this , but I don't think I can get this done. – kiran Dec 29 '14 at 15:34
  • 1
    If you knew you always had two spaces, you could just add that to your pattern. – Sotirios Delimanolis Dec 29 '14 at 15:35
  • 1
    @SotiriosDelimanolis It doesn't always have 2 spaces. Only when the time is less than 10, it has 2 spaces and it is greater than 9, it has 1 space. So it I add 2 spaces in the pattern, if the time is greater than 9 hours, then it is failing. So before sending the value to the formatter, I replaced 2 spaces with 1 space which is working for now. – kiran Dec 29 '14 at 15:41
  • @kiran - that is probably the best solution. I have updated the answer to reflect that and also referenced to [this previous answer](http://stackoverflow.com/questions/14998442/ignore-any-white-space-or-new-line-in-java-date-compare) – wassgren Dec 29 '14 at 18:19

1 Answers1

1

Edit: after more info from the OP the answer has been slightly changed.

You can use the following pattern (that you defined).

"MMM dd yyyy hh:mma"

But, since your input strings varies depending on if it is a 2 digit hour or a one digit hour I suggest that you pre-process the values by using the String.replace method (as suggested in this answer).

@Test
public void test() throws JsonProcessingException {
    final String value1 = "Nov 24 2014  2:40PM"; // Double space
    final String value2 = "Nov 24 2014 11:40PM"; // Single space

    // Set up a test time zone
    final ZoneId clientTimeZone = ZoneId.systemDefault();

    // Create the formatter (as previously)
    DateTimeFormatter df = DateTimeFormat.forPattern("MMM dd yyyy hh:mma");


    DateTime temp1 = 
        df.withZone(DateTimeZone.forTimeZone(TimeZone.getTimeZone(clientTimeZone)))
               .withOffsetParsed()
               .parseDateTime(value1.replace("  ", " ")); // replace double space with single space

    DateTime temp2 = 
        df.withZone(DateTimeZone.forTimeZone(TimeZone.getTimeZone(clientTimeZone)))
                .withOffsetParsed()
                .parseDateTime(value2.replace("  ", " ")); // always replace to be sre

    DateTime date1 = temp1.toDateTime(DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/New_York")));
    DateTime date2 = temp2.toDateTime(DateTimeZone.forTimeZone(TimeZone.getTimeZone("America/New_York")));
    Timestamp ts1 = new Timestamp(date1.getMillis());
    Timestamp ts2 = new Timestamp(date2.getMillis());
}

If you are using Java 8 it is also a possibility to skip Joda and instead use the new Java 8 time and date functions from the java.time packages. E.g.

DateTimeFormatter df = DateTimeFormatter.ofPattern("MMM dd yyyy h:ma");
Community
  • 1
  • 1
wassgren
  • 18,651
  • 6
  • 63
  • 77
  • I tried this format, but I am getting the same exception.java.lang.IllegalArgumentException: Invalid format: "Nov 24 2014 2:40PM" is malformed at " 2:40PM" – kiran Dec 29 '14 at 15:18
  • @SotiriosDelimanolis Hard to say. "hh" means the hour should be zero-padded, but 2 isn't zero-padded... incidentally, shouldn't the day also be "d" instead of "dd" for the same reason? – Powerlord Dec 29 '14 at 15:20
  • @SotiriosDelimanolis Actually, nevermind. "When parsing, any number of digits are accepted." for numbers, of which day of month; hour of halfday; and minute are all considered. – Powerlord Dec 29 '14 at 15:23