RFC822 Timezone Parsing in Java

2019-04-25 02:37发布

问题:

I have a JS date that is being converted by Dojo into RFC822 format. The function call - dojo.date.toRfc3339(jsDate), generates the following date - 2007-02-26T20:15:00+02:00.

I have an application that uses a Java date SimpleDateFormat to parse in the dates generated above. I am having problems parsing this date format due to the timezone. I have attempted to use

yyyy-mm-DD'T'hh:mm:ssZ

This fails as the 'Z' for timezone doesn't expect a ':' character. Does anyone know how I would specify a pattern to handle a RFC822 date with the ':'?

revision:

Thanks for correctly interpreting what I am trying to do :) I was meant to say the date is generating in RFC3339 and I needed RFC822. Looks like I will have to override the JavaScript. I was hoping that I wouldn't have to do that and could specify a date format pattern without having to modify any Java Code as the date format is simply injected into a Spring bean of an application.

Just for completeness, is there a way to specify in a date format expression to ignore characters in the sequence (without doing String manipulation/replacement)? In this case I'd be saying ignore any ':' or just ignore the timezone all together?

回答1:

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateUtil {

    public static Date ParseRFC3339DateFormat(String p_date)
    {
        try{
            SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ");
            String dts = p_date.replaceAll("([\\+\\-]\\d\\d):(\\d\\d)","$1$2");
            return formatter.parse(dts);
        }catch (Exception e) {
                return null;
        }
    }
}


回答2:

This works

SimpleDateFormat format = new SimpleDateFormat("yyyy-mm-DD'T'hh:mm:ssZ");
format.parse("2007-02-26T20:15:00+02:00".replaceAll("([\\+\\-]\\d\\d):(\\d\\d)","$1$2"));

(Note I've taking the final colon out of the format after the 'Z' format specifier.)



回答3:

RFC822 does not allow a colon to be in the time zone portion of date. It expects just the 4 digits. The name of that Dojo method indicates that it is using RFC3339. It seems that is practically the same format as ISO8601. It just so happens that Joda Time has ISODateTimeFormat which is ISO8601 compatible if you are able to use that library. The method dateTimeNoMillis() looks like a match with the Dojo format. It really is nicer than the standard Java date and time API. Otherwise highlycaffeinated's suggestion would be the way to go.

Updated in response to Jamen's update

Isn't there a way to have Dojo use a format that doesn't include the timezone? Then you can adjust the format on the Java side to match. I don't know much about Dojo and I haven't been able to find any documentation on the toRfc3339 function it provides.



回答4:

I'd strip the ':' out of the timezone and use the format you have above.



回答5:

Instead of using dojo.date.toRfc3339(jsDate) you could create your own function with a custom format string.

Something like the following would remove the colon and should be parsable by your java format.

function toRfc3339String(jsDate){
    return dojo.date.locale.format(jsDate,{selector: 'date', datePattern:'yyyy-MM-dd\'T\'hh:mm:ssZ'});
}


回答6:

You can do this generically without Java 7. I have asked 2 questions in StackOverflow on this, within 2012, so there is a solution that does not need any third party libraries.

Just check the implementation presented in the description of my latest question, which also points to the earlier one that discusses exactly this issue.



回答7:

In Java 8 you can use:

Instant.from(DateTimeFormatter.RFC_1123_DATE_TIME.parse( rfc822Time ) );

FYI: https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html#RFC_1123_DATE_TIME