我正在尝试将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-08-31 20:40:59 2)2017-09-01 11:16:24.024
以下是输出: 1)2017-08-31 20:40:59 2)2017-09-01 11:16:24
答案 0 :(得分:2)
当你这样做时:
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);
打印:
Tue Aug 01 07:00:00 BRT 2017
因为在8月1日 st ,UTC的上午10点相当于圣保罗的上午7点。 此结果将根据您的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-08-01 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-08-01 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
或PST
),因为它们是ambiguous and not standard。
您可以致电TimeZone.getAvailableIDs()
获取可用时区列表(并选择最适合您系统的时区)。
旧类(Date
,Calendar
和SimpleDateFormat
)有lots of problems和design issues,它们将被新API取代。< / p>
在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());
答案 1 :(得分:0)
更改行
dateFormat.setTimeZone(TimeZone.getDefault());
到
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));