关于java:将小时分钟字符串时间转换为utc,反之亦然

Convert hour minute string time to utc and vice versa

我正在尝试以"HH:mm"的格式取一个字符串,并将其从local转换为utc,反之亦然。 这是我到目前为止所拥有的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
    private String doTimeConversion(String time, boolean type) {

    DateFormat dfLocal = new SimpleDateFormat("HH:mm");
    DateFormat dfUTC   = new SimpleDateFormat("HH:mm");
    TimeZone local =  TimeZone.getDefault();
    TimeZone utc   =  TimeZone.getTimeZone("UTC");

    dfLocal.setTimeZone(local);
    dfUTC.setTimeZone(utc);

    Date date;
    String newTime ="00:00";
    try {
        //If true: local to utc/If false: utc to local
        if (type) {
            date = dfLocal.parse(time);
            newTime = dfUTC.format(date);
        } else {
            date = dfUTC.parse(time);
            newTime = dfLocal.format(date);
        }

    } catch (ParseException e) {
        e.printStackTrace();
    }
    return newTime;
}

这似乎主要起作用,但我遇到的问题是,虽然我应该使用TimeZone.getDefault()抓住设备时间,但它没有考虑夏令时。 而不是将12:00(UTC)更改为08:00(EDT),而是将其更改为07:00(美国东部时间)。

总的来说,我只是希望能够花时间用户输入(字符串)并使用设备时区来假设用户输入的是根据他们的时区并将其转换为utc以及从utc返回到 设备时区。


使用ThreeTenABP我能够将我的代码转换为以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
    /**
     * @param d      int arr that holds date vals
     * @param from   Time zone to convert from
     * @param to     Time zone to convert to
     * @return       Converted date as String
     */

    protected String doConvertTime(int[] d, ZoneId from, ZoneId to, DateTimeFormatter format){
        LocalDateTime before = LocalDateTime.of(d[0], d[1], d[2], d[3], d[4]);
        ZonedDateTime beforeTime = ZonedDateTime.of(before, from);
        ZonedDateTime afterTime = beforeTime.withZoneSameInstant(to);
        return afterTime.format(format);
    }

int [] d:

我正在解析保存值的字符串片段并将它们放入一个传递给上面显示的函数的整数数组中。这似乎比直接从String解析更容易,因为我正在处理多个字符串。这样我就能确保将所有数据压缩到一个区域。

ZoneId来自& ZoneId:

我在主函数的开头初始化了两个ZoneId,这样我可以互换使用它们。例如。 local to utc:from = local,to = utc / utc to local:from = utc,to = local。实际上,可以使用任何两个时区。

DateTimeFormatter格式:

我只想以"MM / dd / yy"或"HH:mm"的格式返回一个String,因为这是我之前保持这些值的字符串的分离方式。但是,我需要有关日期的所有数据,以确保正在使用正确的时区以及由于时区更改而未更改日期,月份或年份。例如。 2018-12-31 22:00(美国东部时间)"America / New_York" - > 2019-01-01 03:00(UTC)( - 05:00偏移)如果我只有时间(HH:mm)值那么日期不会改变。


java.time

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import org.threeten.bp.LocalDate;
import org.threeten.bp.LocalDateTime;
import org.threeten.bp.LocalTime;
import org.threeten.bp.ZoneId;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.ZonedDateTime;

public class ConvertTimeToAndFromUtc {

    /** @param type If true: local to utc/If false: utc to local */
    private static String doTimeConversion(String time, boolean type) {
        ZoneId localZone = ZoneId.systemDefault();
        LocalTime lt = LocalTime.parse(time);
        LocalDateTime ldt = LocalDate.now(localZone).atTime(lt);
        ZonedDateTime resultTime;
        if (type) {
            resultTime = ldt.atZone(localZone).withZoneSameInstant(ZoneOffset.UTC);
        } else {
            resultTime = ldt.atOffset(ZoneOffset.UTC).atZoneSameInstant(localZone);
        }
        LocalTime newTime = resultTime.toLocalTime();
        return newTime.toString();
    }

    public static void main(String[] args) {
        System.setProperty("user.timezone","Asia/Gaza");

        System.out.println("09.21 local to UTC:" + doTimeConversion("09:21", true));
        System.out.println("23:13 UTC to local:" + doTimeConversion("23:13", false));
    }

}

今天打印上面的程序(在Java 7上测试):

1
2
09.21 local to UTC: 06:21
23:13 UTC to local: 02:13

加沙地带在一年的这个时间偏移+03:00,在标准/正常时间偏移+02:00,所以看来转换是考虑到夏令时(DST)(后一次转换是在午夜过后)。

我正在使用java.time,现代Java日期和时间API。您使用的日期时间类DateFormatSimpleDateFormatTimeZoneDate都已过时,并且存在一系列设计问题。他们也不适合手头的问题。

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

是的,java.time适用于较旧和较新的Android设备。它至少需要Java 6。

  • 在Java 8及更高版本和更新的Android设备上(来自API级别26),现代API内置。仅在这种情况下从java.time包导入日期时间类(不是org.threeten.bp)。
  • 在Java 6和7中获取ThreeTen Backport,新类的后端端口(适用于JSR 310的ThreeTen;请参见底部的链接)。
  • 在(较旧的)Android上使用Android版的ThreeTen Backport。它被称为ThreeTenABP。并确保从子包中导入org.threeten.bp的日期和时间类。

链接

  • Oracle教程:日期时间,解释如何使用java.time
  • Java规范请求(JSR)310,其中首先描述java.time
  • ThreeTen Backport项目,java.time的后端到Java 6和7(用于JSR-310的ThreeTen)。
  • ThreeTenABP,Android版ThreeTen Backport
  • 问题:如何在Android项目中使用ThreeTenABP,有一个非常详尽的解释。