如何在Android中转换具有不同时区的时间字符串格式

时间:2019-07-08 10:34:37

标签: android date datetime calendar datetime-format

我有一个类似yyyy-MM-dd'T'HH:mm:ss.SSSSSS的时间字符串格式,时区为“ GMT + 05:30”。我需要将此格式转换为yyyy-MM-dd'T'HH:mm:ss.SSS'Z'格式,并使用不同的时区-“ GMT0:00”。我在下面的函数中编写了将具有不同时区的时间字符串转换的功能。它工作正常,但无法更改时间。

public static String getUTCDate(String dateString) {
    String oldDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS";
    String newDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String result = "";
    SimpleDateFormat simpleDateFormatOld;
    SimpleDateFormat simpleDateFormatNew;

    try {
        simpleDateFormatOld = new SimpleDateFormat(oldDateFormat,Locale.US);
        simpleDateFormatNew = new SimpleDateFormat(newDateFormat,Locale.US);
        simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        result = simpleDateFormatNew.format(simpleDateFormatOld.parse(dateString));
    }
    catch(Exception e) {
        ExceptionHandler.handleException(e);
    }
    return result;
}

示例:我传递了2019-07-11T21:28:02.8469576日期时间字符串。但是作为回报,我得到了2019-07-11T21:28:02.846Z日期时间字符串,而没有更改时间。

如何更新字符串的时间?

4 个答案:

答案 0 :(得分:1)

对于大多数用途,您不希望将时间点从一个时区的一种字符串格式转换为另一时区的另一种字符串格式。在程序中,将日期和时间保存在正确的日期时间对象中,而不是字符串中(就像您不会在字符串中保留整数或浮点值一样)。如果只需要时间点(而不是原始GMT偏移量+05:30),则Instant类是正确的使用类。当程序接受字符串输入时,首先将其解析并转换为Instant并保持原样。仅在需要输出字符串时,才将时间格式化为字符串并传递出去。

java.time和ThreeTenABP

解析并转换输入

    ZoneId originalZone = ZoneId.of("Asia/Kolkata");

    Instant time = LocalDateTime.parse("2019-07-11T21:28:02.8469576")
            .atZone(originalZone)
            .toInstant();

    System.out.println(time);

换算后的时间显示为:

  

2019-07-11T15:58:02.846957600Z

在大多数情况下,请勿将时区作为GMT的裸露偏移量。命名时区可以更好地向读者解释为什么选择该时区,并且在偏移量发生更改(这种情况比您想像的更多)时更能适应未来的需求。我正在利用您的字符串为ISO 8601格式的事实。在这种情况下,我们不需要提供明确的格式化程序。顺便说一句,您的示例字符串以秒为单位的小数点为7,而您的oldDateFormat似乎要为6。这在这里无关紧要,因为LocalDateTime.parse接受0到9的小数。

格式化输出

您要求的输出是ISO 8601的另一个变体。上面的输出非常相似,因为它也是ISO 8601,只有小数太多。因此,这次我们应用明确的格式:

    ZoneOffset newOffset = ZoneOffset.UTC;
    DateTimeFormatter newFormatter = new DateTimeFormatterBuilder()
            .append(DateTimeFormatter.ISO_LOCAL_DATE)
            .appendLiteral('T')
            .appendPattern("HH:mm:ss.SSSX")
            .toFormatter();

    String formattedUtcDateTime = time.atOffset(newOffset).format(newFormatter);
    System.out.println(formattedUtcDateTime);
  

2019-07-11T15:58:02.846Z

我们看到现代的Java日期和时间API java.time迫使我们指定时区偏移,所以忘记了(就像您在问题代码中所做的那样,导致意外的输出)根本不可能。

我建议不要使用SimpleDateFormat和TimeZone

您尝试使用的日期时间类SimpleDateFormatTimeZone的设计很差,而且已经过时,尤其是前者特别麻烦。同样,无法 SimpleDateFormat可以正确解析秒上的6或7个小数;它仅支持毫秒,正好是三个小数。相反,我使用的是java.time,这是现代的Java日期和时间API。我发现使用它非常好。

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

是的,java.time在较新和较旧的Android设备上均可正常运行。它只需要至少 Java 6

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

链接

答案 1 :(得分:0)

尝试一下:

  public static String getUTCDate(String dateString) {
    String oldDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS";
    String newDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String result = "";
    SimpleDateFormat simpleDateFormatOld;
    SimpleDateFormat simpleDateFormatNew;

    try {
        simpleDateFormatOld = new SimpleDateFormat();
        simpleDateFormatOld.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        simpleDateFormatOld.applyPattern(oldDateFormat);
        simpleDateFormatNew = new SimpleDateFormat(newDateFormat, Locale.US);
        result = simpleDateFormatNew.format(simpleDateFormatOld.parse(dateString));
    }
    catch(Exception e) {
        e.printStackTrace();
    }
    return result;
}

对我有用。只是在对日期应用日期模式之前设置simpleDataFormatOld对象的时区。

答案 2 :(得分:0)

编辑:尝试此方法:

DECLARE  @GRP NVARCHAR(40) = 'A.3.3.3.1';

WITH items AS (
    SELECT  G.GRP,
            ISNULL(G.PARENTGRP, '')  AS ParentGroup,
            0 AS Level    
    FROM #SMGROUP G 
    WHERE G.GRP = @GRP

    UNION ALL

    SELECT  G.GRP, 
            G.PARENTGRP, 
            Level + 1    
    FROM #SMGROUP G 
    INNER JOIN items itms 
        ON itms.ParentGroup = G.GRP
)

SELECT TOP 1 Grp
FROM items
ORDER BY Level DESC

有2个更改: 1.还要为新格式设置时区。

    public static String getUTCDate(String dateString) {
    Log.d(TAG,"input : "+dateString);
    String oldDateFormat = "yyyy-MM-dd'T'HH:mm:ss";
    String newDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String result = "";
    SimpleDateFormat simpleDateFormatOld;
    SimpleDateFormat simpleDateFormatNew;

    try {
        simpleDateFormatOld = new SimpleDateFormat(oldDateFormat, Locale.US);
        simpleDateFormatNew = new SimpleDateFormat(newDateFormat,Locale.US);
        simpleDateFormatOld.setTimeZone(TimeZone.getTimeZone("GMT+05:30"));
        simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT0:00"));
        result = simpleDateFormatNew.format(simpleDateFormatOld.parse(dateString));
    }
    catch(Exception e) {
        ExceptionHandler.handleException(e);
    }
    return result;
}
  1. 从oldDateFormat中删除毫秒模式。

    String oldDateFormat =“ yyyy-MM-dd'T'HH:mm:ss”;

答案 3 :(得分:0)

我也通过添加oldDateFormat的时区解决了这个问题。

例如:

simpleDateFormatOld.setTimeZone(TimeZone.getTimeZone("GMT+5:30"));
simpleDateFormatNew.setTimeZone(TimeZone.getTimeZone("GMT+0:00"));