的Java UTC到当地时间不灵
我想UTC转换为本地时间,的Java UTC到当地时间不灵
下面是我使用的代码,
public static String utcToLocalDateFormat(String dateString) {
Log.i("DateFormat", "utcToLocal:Before===>" + dateString);
String formattedDate = null;
if (dateString != null) {
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
dateFormat.setTimeZone(TimeZone.getDefault());
Date date = null;
try {
Log.i("DateFormat", "getTimeZone===>" +dateFormat.getTimeZone());
date = dateFormat.parse(dateString);
System.out.println(date);
} catch (ParseException e) {
e.printStackTrace();
}
formattedDate = dateFormat.format(date);
Log.i("DateFormat", "utcToLocal:After===>" + formattedDate);
}
return formattedDate;
}
但问题是,之前和之后的时区转换时间它不会转换为UTC到当地时间。 任何帮助表示赞赏。
以下是我的输入: 1)2017年8月31日20时四十分59秒 2)2017年9月1日11:16:24.024
以下是输出: 1)2017-08- 31 20时40分59秒 2)2017年9月1日11点16分24秒
改变线
dateFormat.setTimeZone(TimeZone.getDefault());
到
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
当你这样做:
dateFormat.setTimeZone(TimeZone.getDefault());
然后解析String
,你说的格式:“我会给你在这个时区的日期和时间的字符串”。如您使用TimeZone.getDefault()
,它将使用JVM的默认时区。所以,第一件事就是告诉格式化使用UTC在解析时:
DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use UTC to parse
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));
....
date = dateFormat.parse(dateString);
我与dateString
测试等于2017-08-01 10:00:00
。因此,date
将等于2017-08-01 10:00:00 UTC
。当您用System.out.println
打印日期时,它会调用toString()
并将其转换为JVM的默认时区。
在我使用的JVM,默认的时区为America/Sao_Paulo
,所以当我把这个:
System.out.println(date);
它打印:
周二8月1日07:00:00 BRT 2017年
因为在8月1日,上午10时在UTC相当于在圣保罗7 AM。 这将导致根据您的JVM默认时区更改。
如果你想打印日期,但日期和时间等同于另一个时区(UTC相比其他),你需要用不同的时区设定的另一格式:
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use my default timezone to format (America/Sao_Paulo)
dateFormat2.setTimeZone(TimeZone.getDefault());
formattedDate = dateFormat2.format(date);
这将打印:
2017年8月1日07:00:00
而不是默认的时区,你可以使用任何你想要的时区(我使用America/New_York
为例):
DateFormat dateFormat2 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
// use New York timezone
dateFormat2.setTimeZone(TimeZone.getTimeZone("America/New_York"));
formattedDate = dateFormat2.format(date);
这将转换的日期/时间到纽约的时区:
2017年8月1日06:00:00
如果您想要在UTC中打印日期/时间,则不需要创建另一个格式化程序,只需使用第一个格式程序(因为它已设置为UTC)。
JVM的默认时区can be changed without notice, even at runtime,所以最好使用特定的一个,而不是只用getDefault()
的。
倾向于使用IANA timezones names(总是格式为Region/City
,如America/Sao_Paulo
或Europe/Berlin
)。 避免使用3字母缩写(如CST
或),因为它们是ambiguous and not standard。
通过调用TimeZone.getAvailableIDs()
,您可以获得可用时区列表(并选择最适合您系统的时区)。
新的日期/时间API
老班(Date
,Calendar
和SimpleDateFormat
)有lots of problems和design issues,他们正在被新的API取代。
在Android中,您可以使用ThreeTen Backport,它是Java 8新日期/时间类的一个很好的后端。要使其工作,您还需要ThreeTenABP(更多关于如何使用它here)。
该API使用起来要容易得多。首先创建一个org.threeten.bp.format.DateTimeFormatter
并将输入String
解析为org.threeten.bp.LocalDateTime
。
然后将其转换为UTC(创建org.threeten.bp.ZonedDateTime
),然后到你想要的时区,并使用其他格式以进行输出:
// date/time with optional milliseconds
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss[.SSS]");
// parse to LocalDateTime
LocalDateTime dt = LocalDateTime.parse(dateString, parser);
// convert to UTC
ZonedDateTime z = dt.atZone(ZoneOffset.UTC);
// convert to another timezone
z = z.withZoneSameInstant(ZoneId.of("America/New_York"));
// format it
// date/time without milliseconds
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(fmt.format(z));
您还可以使用使用ZoneId.systemDefault()
默认的时区,并使用ZoneId.getAvailableZoneIds()
获得所有可用时区。
如果你想要UTC的日期/时间,你可以跳过withZoneSameInstant()
。
要将其转换为java.util.Date
,你可以使用org.threeten.bp.DateTimeUtils
类:
// convert ZonedDateTime to java.util.Date
Date d = DateTimeUtils.toDate(z.toInstant());
谢谢,但我不想指定像时区(TimeZone.getTimeZone(“America/New_York”))你提到的,我的应用程序使用世界的任何部分,它应该根据该时区工作。 – Joe
@Joe我已经更新了答案,使其更加清晰。 – 2017-09-01 13:11:30
能否请您提供一些输入和输出(预期VS你在说什么)? – 2017-09-01 12:25:50
您的'dateFormat'解析输入为本地TZ可以吗? – yegodm
在你的日期格式模式中,你不知道什么时区会传递给你的方法。所以字符串被解析,因为它已经在默认的时区。 – Damian0o