我正在尝试将UTC转换为local,
以下是我正在使用的代码,
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;
}
但是问题是在时区转换时间相同之前和之后。任何帮助都赞赏。
以下是我的输入:1)2017-08-31 20:40:592)2017-09-01 11:16:24.024
以下是输出:1)2017-08-31 20:40:592)2017-09-01 11:16:24
当您做:
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日 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的默认时间区域,而无需通知,因此最好使用特定的时区,而不仅仅是使用getDefault()
。
更喜欢使用IANA时区名称(始终以Region/City
格式,例如America/Sao_Paulo
或Europe/Berlin
)。避免使用3个字母的缩写(例如CST
或PST
),因为它们是模棱两可的,而不是标准的。
您可以通过调用TimeZone.getAvailableIDs()
。
新日期/时间API
旧类(Date
,Calendar
和SimpleDateFormat
)有很多问题和设计问题,它们被新的API替换。
在Android中,您可以使用Threeten Backport,这是Java 8的新日期/时间课程的绝佳备份。为了使它起作用,您还需要三个threetenabp(有关如何在此处使用它的更多信息)。
此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());
更改行
dateFormat.setTimeZone(TimeZone.getDefault());
to
dateFormat.setTimeZone(TimeZone.getTimeZone("UTC"));