在 Java 中更改执行日期的时区



我想更改给定日期的时区。我使用此代码,但我没有得到好的结果。 我的输入是欧洲/巴黎

的"2020-06-16 14:00:00"时间,我想将其更改为 UTC,这意味着我想得到"2020-06-16 12:00:00",但我得到的初始结果是"2020-06-16 14:00:00"。
try {
// Calendar calParis = Calendar.getInstance();
String heure = "1400";
Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2020-06-16");
String hour = heure.substring(0, heure.length() - 2);
String minute = heure.substring(heure.length() - 2);
Calendar cal = Calendar.getInstance();
String datenew = "2020-06-16" + " " + hour + ":" + minute + ":00";
SimpleDateFormat sdfDatenew = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
Date thisDate = sdfDatenew.parse(datenew);
cal.setTime(thisDate);
cal.setTimeZone(TimeZone.getTimeZone("Europe/UTC"));
SimpleDateFormat sdfDate = new SimpleDateFormat("yyyy-mm-dd HH:mm:ss");
String dateISO = null;
dateISO = sdfDate.format(cal.getTime());
System.out.println("Time in ISO: " + dateISO);
} catch (Exception ex) {
}

你来了: 通过这种方式,您可以获取Java-7格式的日期和时间。

public static void main(String[] args) throws ParseException {
String heure = "1400";
Date date = new SimpleDateFormat("yyyy-MM-dd").parse("2020-06-16");
String hour = heure.substring(0, heure.length() - 2);
String minute = heure.substring(heure.length() - 2);
String datenew = "2020-06-16" + " " + hour + ":" + minute + ":00";
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
Calendar calendar = Calendar.getInstance();
Date thisDate = sdf.parse(datenew);
calendar.setTime(thisDate);
sdf.setTimeZone(TimeZone.getTimeZone("PDT"));
System.out.println(sdf.format(calendar.getTime())); // prints 2020-06-16 12:00:00
sdf.setTimeZone(TimeZone.getDefault());
System.out.println(sdf.format(calendar.getTime())); // prints 2020-06-16 14:00:00
}

tl;博士

LocalDateTime
.parse( 
"2020-06-16 14:00:00"
.replace( " " , "T" ) 
)
.atZone(
ZoneId.of( "Europe/Paris" )
)
.toInstant()
.atOffset( ZoneOffset.UTC )
.format(
DateTimeFormatter.ofPattern( "uuuu-MM-dd HH:mm:ss" )
)

查看此代码在 IdeOne.com 实时运行。

2020-06-16 12:01:00

java.time

现代解决方案使用java.time类。

输入字符串缺少时区或偏移量。因此,解析为LocalDateTime对象。

LocalDateTime ldt = LocalDateTime.parse( "2020-06-16 14:00:00".replace( " " , "T" ) ) ;

您肯定地说,这个字符串代表了法国巴黎时区的时刻。

ZoneId zParis = ZoneId.of( "Europe/Paris" ) ;
ZonedDateTime zdt = ldt.atZone( zParis ) ;

从那里调整到您的目标时区。您碰巧想要UTC,因此只需提取Instant即可。

Instant instant = zdt.toInstant() ;

java.time

java.util日期-时间 API 及其格式设置 APISimpleDateFormat已过时且容易出错。建议完全停止使用它们,并切换到 2014 年 3 月作为 Java SE 8 标准库的一部分发布的现代日期-时间 API*

Basil Bourque的答案是正确的,但是当DateTimeFormatter有足够的能力解决这个问题以及更多时,我不String会在使用替代品。

演示:

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 input = "2020-06-16 14:00:00";
DateTimeFormatter dtfInput = DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH);
LocalDateTime ldt = LocalDateTime.parse(input, dtfInput);
ZonedDateTime zdtParis = ldt.atZone(ZoneId.of("Europe/Paris"));
ZonedDateTime zdtUtc = zdtParis.withZoneSameInstant(ZoneId.of("Etc/UTC"));
// Default format
System.out.println(zdtUtc);
// Custom format
DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH);
String output = dtfOutput.format(zdtUtc);
System.out.println(output);
}
}

输出:

2020-06-16T12:00Z[Etc/UTC]
2020-06-16 12:00:00

在线演示

全部在一个语句中:

System.out.println(
LocalDateTime
.parse("2020-06-16 14:00:00", DateTimeFormatter.ofPattern("u-M-d H:m:s", Locale.ENGLISH))
.atZone(ZoneId.of("Europe/Paris"))
.withZoneSameInstant(ZoneId.of("Etc/UTC"))
.format(DateTimeFormatter.ofPattern("uuuu-MM-dd HH:mm:ss", Locale.ENGLISH))
);

在线演示

一些重要注意事项:

  1. 您可以使用单个模式,uuuu-MM-dd HH:mm:ss输入和输出字符串,但我更喜欢使用u-M-d H:m:s进行解析,因为如果您有两位数的年份、一位数的月份、一位数的月份、一位数的一天等,uuuu-MM-dd HH:mm:ss就会失败。对于解析,单个u可以同时满足两位数和四位数的年份表示。同样,单个M可以同时满足一位数和两位数的月份。其他符号的情况类似。
  2. 在这里,您可以使用y而不是u但我更喜欢u而不是y

要了解有关现代日期-时间 API 的更多信息,请参阅跟踪:日期时间


* 出于任何原因,如果你必须坚持使用 Java 6 或 Java 7,你可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目工作,并且您的 Android API 级别仍然不符合 Java-8,请查看通过脱糖提供的 Java 8+ API 和如何在 Android Project 中使用 ThreeTenABP。

最新更新