我的应用程序从服务器获取有关过去事件的日期和时间的响应。但是,我的服务器在另一个时区,因此这里有些棘手。服务器时区为UTC +01:00,而我的时区为UTC +03:00。当我从服务器收到响应时,它们带有UTC +01:00中的时间戳。首先,我尝试将日期作为String接收,对其进行子字符串设置,设置其时区,然后以正确的时间格式和时区返回它。 (我删减了毫秒数的后4位,因为DateFormat否则无效。)

private String getFormattedDate(String date) {
    DateFormat serverDateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX");
    DateFormat finalDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    Calendar calendar = Calendar.getInstance();
    TimeZone timeZone = calendar.getTimeZone();
    serverDateFormat.setTimeZone(timeZone);
    String cutoutDate = date.substring(0,23);
    String cutoutZone = date.substring(27, date.length());
    String dateInProperFormat = cutoutDate + cutoutZone;
    Date finalDate = serverDateFormat.parse(dateInProperFormat);
    return finalDateFormat.format(finalDate);
}


这样可以正确读取并转换所有内容:


  服务器响应:2018-04-30T07:26:55.1524511+01:00->子字符串响应:2018-04-30T07:26:55.152+01:00->最终格式:30-04-2018 09:26:55


但是,毫秒数并不总是7,所以当发生这种情况时,出现了Unparsable date错误。这使我不是以String而是以Date的形式读取日期。这将代码减少到仅5行:

private String getFormattedDate(Date date) {
    SimpleDateFormat finalDateFormat = new SimpleDateFormat("dd-MM-yyyy HH:mm:ss");
    Calendar calendar = Calendar.getInstance();
    TimeZone timeZone = calendar.getTimeZone();
    finalDateFormat.setTimeZone(timeZone);
    return finalDateFormat.format(date);
}


但是现在,时间总是在UTC +01:00中。我试图像这样获取时区:

TimeZone timeZone = TimeZone.getDefault();


但这并没有改变任何东西。在第二种方法中我到底在做错什么?如果需要,我准备共享更多代码。

最佳答案

java.time

private static DateTimeFormatter finalDateTimeFormatter
        = DateTimeFormatter.ofPattern("dd-MM-uuuu HH:mm:ss");
private static ZoneId zone = ZoneId.of("Europe/Istanbul");

private static String getFormattedDate(String dateTime) {
    return OffsetDateTime.parse(dateTime)
            .atZoneSameInstant(zone)
            .format(finalDateTimeFormatter);
}


让我们用您的问题的示例服务器响应进行尝试:

    System.out.println(getFormattedDate("2018-04-30T07:26:55.1524511+01:00"));


这将输出所需的内容:


  30-04-2018 09:26:55


注意事项:


单个参数OffsetDateTime.parse在秒上接受1到9个小数,因此在解析之前,您无需以任何方式操作字符串。
不要将您的UTC偏移量UTC +03:00用作时区。使用非洲/内罗毕,欧洲/莫斯科,亚洲/卡塔尔等时区或适当的时区。它更好地记录了您为什么做自己的工作,并且在偏移量发生更改的情况下,它可以面向未来。发生的次数比您想的要多。


问题:我可以在Android上使用java.time吗?

是的,java.time在较新的Android设备上都能很好地工作。它至少需要Java 6。


在Java 8和更高版本以及更新的Android设备(我知道API级别为26)上,内置了现代API。
在Java 6和7中,获取ThreeTen Backport,即新类的Backport(JSR 310的ThreeTen;请参见底部的链接)。
在较旧的Android上,请使用Android版本的ThreeTen Backport。叫做ThreeTenABP。并确保使用子包从org.threeten.bp导入日期和时间类。


链接


Oracle tutorial: Date Time解释如何使用java.time
Java Specification Request (JSR) 310,其中首先描述java.time
ThreeTen Backport projectjava.time到Java 6和7的反向端口(JSR-310的ThreeTen)。
ThreeTenABP,ThreeTen Backport的Android版
Question: How to use ThreeTenABP in Android Project,具有非常详尽的说明。

关于android - Date()未捕获时区更改,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/50100721/

10-09 06:53
查看更多