从字符串

时间:2017-08-24 06:51:33

标签: android datetime jodatime datetime-parsing

我想要将以下String更改为UTC:

  

Thu Aug 24 07:38:32 GMT + 01:00 2017

我正在使用Joda-Time库。

我知道如何创建新的Datetime例如new dateTime(DateTimeZone.UTC),但如何从上面DateTime创建String个对象?

我尝试过以下操作但获得例外。当然必须有另一种方法来创建DT对象而不会破坏原始的String?如果外部API更改了我的应用程序发送orignal String的方式,我的String操作代码将失败。

DateTimeFormatter df = DateTimeFormat.forPattern("dd-MMM-YYYY HH:mm");
        String strOrigTime = "Thu Aug 24 07:38:32 GMT+01:00 2017";
        DateTime dt = DateTime.parse(strOrigTime, df);

        Log.e(TAG, "dt after parse = " + dt.toString());

错误:

Caused by: java.lang.IllegalArgumentException: Invalid format: "Thu Aug 24 07:38:32 GMT+01:00 2017"
    at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:866)
    at org.joda.time.DateTime.parse(DateTime.java:144)

1 个答案:

答案 0 :(得分:2)

使用的格式(dd-MMM-YYYY HH:mm)表示:日期(dd)后跟-,后跟月份(MMM),后跟-,接着是年份(YYYY),依此类推(check the javadoc了解详情)。

此格式与输入字符串不匹配(输入字符串包含星期几,后跟月份,后跟天,然后是小时/分钟/秒等)。所以第一件事是使用与输入匹配的格式,否则你将总是得到“无效格式”错误。

另一个细节是星期几和月份名称都是英文,因此您还必须使用java.util.Locale指定用于解析输入的语言。如果您不使用区域设置,系统将使用默认设置,并且不保证始终为英语(即使在运行时也可以更改它,因此最好指定一个)。

我还必须将“GMT”添加为文字并调用withOffsetParsed()以使其包含已解析对象中的偏移量(+01:00):

DateTimeFormatter df = DateTimeFormat
    // use a pattern that matches input
    .forPattern("EEE MMM dd HH:mm:ss 'GMT'Z yyyy")
    // use English locale for day of week and month
    .withLocale(Locale.ENGLISH)
    // include the offset (+01:00) in the parsed object
    .withOffsetParsed();
String strOrigTime = "Thu Aug 24 07:38:32 GMT+01:00 2017";
DateTime dt = DateTime.parse(strOrigTime, df);
System.out.println(dt.toString());

输出结果为:

  

2017-08-24T07:38:32.000 + 01:00

然后,您可以将UTC时区设置为此对象:

dt = dt.withZone(DateTimeZone.UTC);
System.out.println(dt.toString());

输出将是:

  

2017-08-24T06:38:32.000Z

请注意,withZone方法保留相同的时刻(两个日期代表相同的时间点),只更改输出中使用的时区。但两个日期都是等价的(它们代表同一时刻,因为07:38在偏移+01:00与UTC中的06:38相同)。

如果您希望将所有日期转换为UTC,您还可以在格式化程序中设置:

// set UTC to the formatter
df = df.withZone(DateTimeZone.UTC);

然后您无需在withZone个对象中调用DateTime:所有已解析的日期都将转换为UTC。

您还告诉“如果外部API更改了我的应用程序发送orignal String的方式,我的String操作代码将失败”

好吧,如果输入String发生变化,你也必须改变你的格式 - 没有别的办法,Joda-Time不能只猜猜格式是什么,你必须告诉它。 / p>

如果你想解析多种格式,有一种方法可以创建一个格式化程序,它使用许多不同的模式并尝试解析每个格式,直到其中一个工作(或者如果没有则抛出异常)。你可以这样做:

// format 1
DateTimeFormatter f1 = DateTimeFormat
    // use a pattern that matches input
    .forPattern("EEE MMM dd HH:mm:ss 'GMT'Z yyyy")
    // use English locale for day of week and month
    .withLocale(Locale.ENGLISH)
    // include the offset (+01:00) in the parsed object
    .withOffsetParsed();

// format 2
DateTimeFormatter f2 = DateTimeFormat.forPattern("dd/MM/yyyy HH:mm:ss Z");
// array of all possible formats
DateTimeParser[] parsers = { f1.getParser(), f2.getParser() };
// formatter that uses all the possible formats
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    // append array of possible formats
    .append(null, parsers)
    // create formatter
    .toFormatter().withLocale(Locale.ENGLISH).withOffsetParsed()
    // set all parsed objects to UTC
    .withZone(DateTimeZone.UTC);

// parse first format
System.out.println(DateTime.parse("Thu Aug 24 07:38:32 GMT+01:00 2017", formatter));
// parse second format
System.out.println(DateTime.parse("24/08/2017 07:38:32 +01:00", formatter));

两个日期将被解析为:

  

2017-08-24T06:38:32.000Z

然后,您可以根据需要向阵列添加新格式。

Java新日期/时间API

Joda-Time处于维护模式,正在被新的API取代,因此我不建议使用它来启动新项目。即使在joda's website中它也说:“请注意,Joda-Time被认为是一个很大程度上”完成“的项目。没有计划大的增强。如果使用Java SE 8,请迁移到java.time(JSR) -310)。“即可。

如果您不能(或不想)从Joda-Time迁移到新API,则可以忽略此部分。

如果您使用的是 Java 8 ,请考虑使用new java.time API。它更容易,less bugged and less error-prone than the old APIs

如果您使用的是 Java< = 7 ,则可以使用ThreeTen Backport,这是Java 8新日期/时间类的绝佳后端。对于 Android ,有ThreeTenABP(更多关于如何使用它here)。

以下代码适用于两者。 唯一的区别是包名称(在Java 8中为java.time,在ThreeTen Backport(或Android的ThreeTenABP)中为org.threeten.bp),但类和方法名称是相同的

解析输入的代码非常相似,格式稍有变化。 我正在使用Instant类,因为您希望以UTC格式输出,而Instant代表UTC时刻:

// format 1
DateTimeFormatter f1 = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O yyyy", Locale.ENGLISH);
// format 2
DateTimeFormatter f2 = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss XXX");
// formatter with both formats
DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    // add format 1
    .appendOptional(f1)
    // add format 2
    .appendOptional(f2)
    // create formatter
    .toFormatter(Locale.ENGLISH);
// parse first format
System.out.println(Instant.from(formatter.parse("Thu Aug 24 07:38:32 GMT+01:00 2017")));
// parse second format
System.out.println(Instant.from(formatter.parse("24/08/2017 07:38:32 +01:00")));

这将输出:

  

2017-08-24T06:38:32Z
  2017-08-24T06:38:32Z