旧的 API(带有 Calendar 和 SimpleDateFormat 类)已经过时并且具有 lots of problems。
您应该考虑使用较新的 API。如果您使用的是 Java 8,请考虑使用 new java.time API。更简单,less bugged and less error-prone than the old APIs。
如果您使用的是 Java ,则可以使用 ThreeTen Backport,它是 Java 8 新日期/时间类的出色反向移植。对于Android,还有ThreeTenABP(更多关于如何使用它here)。
下面的代码适用于两者。
唯一的区别是包名(在 Java 8 中是 java.time,而在 ThreeTen Backport(或 Android 的 ThreeTenABP)中是 org.threeten.bp),但类和方法 names 是相同的。
如果您正在使用包含偏移量的日期/时间,最好的选择是使用 OffsetDateTime 类,它表示带有偏移量的日期和时间。它已经有了解析String的方法:
// parse a date string with offset -07:00
String strDate = "2017-06-19T17:50:51.000-07:00";
OffsetDateTime dt = OffsetDateTime.parse(strDate);
System.out.println(dt.toString()); // 2017-06-19T17:50:51-07:00
输出将是:
2017-06-19T17:50:51-07:00
请注意,默认情况下,toString() 方法不显示小数秒,因为它们为零。如果您想始终显示这 3 位数字,可以使用 DateTimeFormatter:
// use a formatter to always print fraction-of-second with 3 digits
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000-07:00
在这种情况下,输出将是:
2017-06-19T17:50:51.000-07:00
使用不同的偏移量进行测试:
// offset +03:00
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000+03:00");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000+03:00
// UTC: "Z" == offset zero (or "+00:00")
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000Z");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000Z
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000+00:00");
System.out.println(fmt.format(dt)); // 2017-06-19T17:50:51.000Z
如果您仍需使用旧 API (java.util.Calendar),您可以轻松地将其与新类相互转换。
如果java.time 包可用,您可以这样做:
// converting the OffsetDateTime to a Calendar
dt = OffsetDateTime.parse("2017-06-19T17:50:51.000Z");
Calendar c = Calendar.getInstance();
// setting the epoch milli to calendar
c.setTimeInMillis(dt.toInstant().toEpochMilli());
// converting Calendar back to OffsetDateTime (using UTC offset)
dt = OffsetDateTime.ofInstant(c.toInstant(), ZoneOffset.UTC);
// converting Calendar back to OffsetDateTime (using +03:00 offset)
dt = OffsetDateTime.ofInstant(c.toInstant(), ZoneOffset.ofHours(3));
如果您使用的是 ThreeTenABP,则方法 c.toInstant() 将不可用。但是你可以使用org.threeten.bp.DateTimeUtils 类来转换它。所以,你可以使用DateTimeUtils.toInstant(c),而不是c.toInstant():
// conversion for ThreeTenABP
// converting Calendar back to OffsetDateTime (using UTC offset)
dt = OffsetDateTime.ofInstant(DateTimeUtils.toInstant(c), ZoneOffset.UTC);
// converting Calendar back to OffsetDateTime (using +03:00 offset)
dt = OffsetDateTime.ofInstant(DateTimeUtils.toInstant(c), ZoneOffset.ofHours(3));
更新:Youtube API
我检查了Youtube API documentation(不确定您是否正在使用),在示例中它将scheduledStartTime 设置为UTC 日期/时间:
broadcastSnippet.setScheduledStartTime(new DateTime("2024-01-30T00:00:00.000Z"));
根据docs,该字段的格式如下:
广播计划开始的日期和时间。该值以ISO 8601 (YYYY-MM-DDThh:mm:ss.sZ) 格式指定。
所以,我们只需要创建一个格式化程序来获取这种格式的String:
// your date/time, in -07:00 offset
String strDate = "2017-06-19T17:50:51.000-07:00";
OffsetDateTime odt = OffsetDateTime.parse(strDate);
// formatter
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSX");
// convert to UTC
String utc = formatter.format(odt.withOffsetSameInstant(ZoneOffset.UTC));
System.out.println(utc); // 2017-06-20T00:50:51.000Z
输出将采用 youtube 示例中使用的相同格式:
2017-06-20T00:50:51.000Z