我想要将以下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)
答案 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
然后,您可以根据需要向阵列添加新格式。
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