5

我对 Java 还是很陌生,我对使用SimpleDateFormatand有点卡住Calendar。我有一个 Date-Object 并想提取一个 GMT 日期字符串,如yyyy-MM-dd HH:mm:ss. 我住在德国,目前我们是 GMT +0200。我的日期对象的时间是例如2011-07-18 13:00:00。我现在需要的是2011-07-18 11:00:00. 我的时区的偏移量应该自动计算。

我尝试过这样的事情,但我想某处有问题:

private String toGmtString(Date date){
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    TimeZone timeZone = TimeZone.getDefault();
    Calendar cal = Calendar.getInstance(new SimpleTimeZone(timeZone.getOffset(date.getTime()), "GMT"));
    sd.setCalendar(cal);
    return sd.format(date);
}

在某些设备上,日期字符串会像我想要的那样返回。在其他设备上,偏移量计算不正确,我从输入日期对象接收日期和时间。你能给我一些提示或建议吗?我想我获得默认时区的方法不起作用?

4

3 回答 3

5
private String toGmtString(Date date){
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    sd.setTimeZone(TimeZone.getTimeZone("GMT"));
    return sd.format(date);
}

您不需要创建新的SimpleTimeZone,因为您没有发明新的时区 - 您的程序中有 2 个现有时区,GMT 和您的默认时区。

您也不需要修改现有的日期对象,因为您不想表示不同的时间点 - 您只需要不同的方式来显示相同​​的时间点。

您需要做的就是告诉SimpleDateFormat在格式化中使用哪个时区。

于 2011-07-18T10:40:14.643 回答
2
private String toGmtString(Date date){
    //date formatter
    SimpleDateFormat sd = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    //getting default timeZone
    TimeZone timeZone = TimeZone.getDefault();
    //getting current time
    Calendar cal = Calendar.getInstance()
    cal.setTime(date) ;
    //adding / substracting curren't timezone's offset
    cal.add(Calendar.MILLISECOND, -1 * timeZone.getRawOffset());    
    //formatting and returning string of date
    return sd.format(cal.getTime());
}
于 2011-07-18T09:25:33.237 回答
0

java.time

使用java.time现代日期时间 API,有很多方法可以做到这一点:

  1. 解析为LocalDateTime➡️ 将其与您的时区结合以获得ZonedDateTime➡️ 转换为Instant➡️ 转换为ZonedDateTimeusingInstant#atZone和 UTC 时区。
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();

        ZonedDateTime zdtUtc = instant.atZone(ZoneId.of("Etc/UTC"));

        System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
    }
}
  1. 解析为LocalDateTime➡️ 将其与您的时区结合以获得ZonedDateTime➡️ 转换为Instant➡️ 转换为ZonedDateTimeusingZonedDateTime#ofInstant和 UTC 时区。
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        Instant instant = ldt.atZone(ZoneId.of("Europe/Berlin")).toInstant();

        ZonedDateTime zdtUtc = ZonedDateTime.ofInstant(instant, ZoneId.of("Etc/UTC"));

        System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
    }
}
  1. 使用ZonedDateTime#withZoneSameInstant
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);

        LocalDateTime ldt = LocalDateTime.parse(strDateTime, dtf);

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        ZonedDateTime zdtPak = ldt.atZone(ZoneId.of("Europe/Berlin"));

        ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));

        System.out.println(zdtUtc.format(dtf)); // 2011-07-18 11:00:00
    }
}
  1. 使用DateTimeFormatter#withZoneZonedDateTime#withZoneSameInstant
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

public class Main {
    public static void main(String[] args) {
        String strDateTime = "2011-07-18 13:00:00";

        // Using ZoneId.of("Europe/Berlin") for the demo. Change it to
        // ZoneId.systemDefault()
        DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH)
                                        .withZone(ZoneId.of("Europe/Berlin"));

        ZonedDateTime zdtPak = ZonedDateTime.parse(strDateTime, dtfInput);

        ZonedDateTime zdtUtc = zdtPak.withZoneSameInstant(ZoneId.of("Etc/UTC"));

        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
        System.out.println(zdtUtc.format(dtfOutput)); // 2011-07-18 11:00:00
    }
}

Trail: Date Time了解有关现代日期时间 API *的更多信息。


* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和 Android API 工作level 仍然不符合 Java-8,请检查Java 8+ APIs available through desugaringHow to use ThreeTenABP in Android Project

于 2021-05-16T11:29:03.120 回答