Android解析字符串到日期 - 未知模式字符'X'

Mat*_*Mav 43 java android date simpledateformat

Service从网上获取日期字符串,然后我想把它削减到Date对象.但不知何故应用程序崩溃.这是我正在解析的字符串:2015-02-05T05:20:02+00:00

onStartCommand()

String datetime = "2015-02-05T05:20:02+00:00";
Date new_date = stringToDate(datetime);
Run Code Online (Sandbox Code Playgroud)

stringToDate()

private Date stringToDate(String s){
    DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
    try{
        return df.parse(s);
    }catch(ParseException e){
        e.printStackTrace();
    }
    return null;
}
Run Code Online (Sandbox Code Playgroud)

logcat的:

02-06 20:37:02.008: E/AndroidRuntime(28565): FATAL EXCEPTION: main
02-06 20:37:02.008: E/AndroidRuntime(28565): Process: com.dotmav.runescapenotifier, PID: 28565
02-06 20:37:02.008: E/AndroidRuntime(28565): java.lang.RuntimeException: Unable to start service com.dotmav.runescapenotifier.GEService@384655b5 with Intent { cmp=com.dotmav.runescapenotifier/.GEService }: java.lang.IllegalArgumentException: Unknown pattern character 'X'
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2881)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.app.ActivityThread.access$2100(ActivityThread.java:144)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1376)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.os.Handler.dispatchMessage(Handler.java:102)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.os.Looper.loop(Looper.java:135)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.app.ActivityThread.main(ActivityThread.java:5221)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at java.lang.reflect.Method.invoke(Native Method)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at java.lang.reflect.Method.invoke(Method.java:372)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:899)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
02-06 20:37:02.008: E/AndroidRuntime(28565): Caused by: java.lang.IllegalArgumentException: Unknown pattern character 'X'
02-06 20:37:02.008: E/AndroidRuntime(28565):    at java.text.SimpleDateFormat.validatePatternCharacter(SimpleDateFormat.java:314)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at java.text.SimpleDateFormat.validatePattern(SimpleDateFormat.java:303)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:356)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at java.text.SimpleDateFormat.<init>(SimpleDateFormat.java:249)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at com.dotmav.runescapenotifier.GEService.stringToDate(GEService.java:68)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at com.dotmav.runescapenotifier.GEService.onStartCommand(GEService.java:44)
02-06 20:37:02.008: E/AndroidRuntime(28565):    at android.app.ActivityThread.handleServiceArgs(ActivityThread.java:2864)
02-06 20:37:02.008: E/AndroidRuntime(28565):    ... 9 more
Run Code Online (Sandbox Code Playgroud)

编辑: onDestroy()为定期更新设置警报...

AlarmManager alarm = (AlarmManager)getSystemService(ALARM_SERVICE);
alarm.set(
    AlarmManager.RTC_WAKEUP,
    System.currentTimeMillis() + (1000 * 60),
    PendingIntent.getService(this, 0, new Intent(this, GEService.class), 0)
);
Run Code Online (Sandbox Code Playgroud)

fla*_*yte 41

Android版本SimpleDateFormat不支持该X模式因此XXX不起作用,而是您可以使用ZZZZZ哪个相同并以格式输出时区+02:00(或-02:00取决于本地时区).

  • 请注意,Android文档目前声称`SimpleDateFormat`*支持`X`.但他们错了./sf/answers/3279918211/ (3认同)
  • 对我不起作用。这个 `2017-04-01T17:31:00+02:00` 可以被 Java 的 `yyyy-MM-dd'T'HH:mm:ssXXX` 解析,但不能在 Android 中解析。这个 `yyyy-MM-dd'T'HH:mm:ssZZZZZ` 永远不匹配,Android 和 Java 都不匹配。 (2认同)
  • 这应该是公认的答案 - 简单的解决方案,而不会丢失目标格式。 (2认同)

Roh*_*5k2 29

从中删除"XXX"

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX");
Run Code Online (Sandbox Code Playgroud)

一切都会好起来的.

浏览可在SimpleDateFormat构造函数中使用的符号列表.这是文档

可能你正在寻找 "yyyy-MM-dd'T'HH:mm:ss.SSSZ"

将您的代码更改为

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); 
Run Code Online (Sandbox Code Playgroud)

要么

DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ"); // if timezone is required
Run Code Online (Sandbox Code Playgroud)

  • 即使android开发者文档显示"XXX"格式,这对我不起作用,也会抛出illegalArgumentException (13认同)
  • 在java 7中,允许使用ISO 8601时区的模式,如-08; -0800; -08:00.SeeJava doc http://docs.oracle.com/javase/7/docs/api/java/text/SimpleDateFormat.html (6认同)
  • yyyy-MM-dd'T'HH:mm:ss不会处理日期的+00:00时区部分.这是用z处理的. (4认同)

Wah*_*Haq 14

没有人提到过关于pre-nougat设备上发生的这个错误,所以我想分享我的答案,也许这对那些因为它而到达这个线程的人有帮助.

这个答案正确地提到"X"仅支持Nougat +设备.我仍然看到文档建议使用"yyyy-MM-dd'T'HH:mm:ss.SSSXXX"而不确定为什么他们不明确这一点.

对我来说,yyyy-MM-dd'T'HH:mm:ssXXX工作正常,直到我试图在6.0设备上测试它,它开始崩溃,这导致我研究这个主题.更换它yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ已解决了该问题,适用于所有5.0+设备.


Tha*_*nos 11

您使用的是错误的日期格式化程序.

请改用: DateFormat df = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");

我认为与Java 7相比,android使用Z(如在Java 6中)用于时区而不是X.所以,将用于您的日期格式.

  • 偏移有三种模式字母.小写的"z"用于"通用时区",如"PST"或其他各种格式.大写`Z`用于RFC 822偏移.在Java 7中,`X`是ISO-8601时区的正确字符(+/ - ####或"Z",没有与UTC的偏移.)`X`在非Android单元测试中的工作方式与预期相同但导致运行Android 6.0的手机异常. (3认同)

Ale*_*r K 8

由于Z和XXX不同,我实现了以下解决方法:

// This is a workaround from Z to XXX timezone format
new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ") {

    @Override
    public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos) {
        StringBuffer rfcFormat = super.format(date, toAppendTo, pos);
        return rfcFormat.insert(rfcFormat.length() - 2, ":");
    }

    @Override
    public Date parse(String text, ParsePosition pos) {
        if (text.length() > 3) {
            text = text.substring(0, text.length() - 3) + text.substring(text.length() - 2);
        }
        return super.parse(text, pos);
    }
}
Run Code Online (Sandbox Code Playgroud)


小智 6

Android SimpleDateFormat与Java 7 SDK不同,不支持"X"来解析ISO 8601.您可以使用"Z"或"ZZZZZ"样式格式化并以编程方式将时区设置为UTC.这是一个util类:

public class DateUtil {

    public static final String iso8601DatePattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ";
    public static final DateFormat iso8601DateFormat = new SimpleDateFormat(iso8601DatePattern);
    public static final TimeZone utcTimeZone = TimeZone.getTimeZone("UTC");

    static {
        iso8601DateFormat.setTimeZone(utcTimeZone);
    }

    public static String formatAsIso8601(Date date) {

        return iso8601DateFormat.format(date);
    }
}
Run Code Online (Sandbox Code Playgroud)