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

时间:2018-10-15 14:47:03

标签: java android datetime timezone

我正在尝试采用“ HH:mm”格式的字符串,并将其从本地转换为utc,反之亦然。这是我到目前为止的内容:

    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(EST)。

总的来说,我只想能够把握用户输入的时间(字符串)并使用设备时区来假设用户输入的时间是根据其时区并将其转换为utc还是从utc返回设备时区。

2 个答案:

答案 0 :(得分:1)

java.time

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上测试):

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,即新类的backport(JSR 310的ThreeTen;请参见底部的链接)。
  • 在(较旧的)Android上,使用Android版本的ThreeTen Backport。叫做ThreeTenABP。并确保您使用子包从org.threeten.bp导入日期和时间类。

链接

答案 1 :(得分:1)

使用ThreeTenABP,我能够将代码转换为以下内容:

    /**
     * @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片段,并将它们放入传递给上述函数的整数数组中。这似乎比直接从String解析容易,因为我正在使用多个String。通过这种方式,我可以确保所有数据都被压缩到一个区域中。

ZoneId从&ZoneId到:

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

DateTimeFormatter格式:

我只想返回格式为“ MM / dd / yy”或“ HH:mm”的字符串,因为这是我持有这些值的字符串被分开的方式。但是,我需要有关日期的所有数据,以确保使用了正确的时区,并且由于时区的更改,日,月甚至年都没有更改。例如。 2018-12-31 22:00(EST)“美国/纽约”-> 2019-01-01 03:00(UTC)(-05:00偏移)如果我只有时间(HH:mm)值,则日期不会改变。