好你发现SimpleDateFormat
的解决方案。我只想添加更多关于它的见解(主要是因为旧类(Date
,Calendar
和SimpleDateFormat
)具有lots of problems和design issues,并且它们正在被新的API替换)。
输入String
(2017-09-16T05:06:18.157
)仅包含日期(年/月/日)和时间(小时/分钟/秒/毫秒),但没有时区信息。因此,在致电parseDateTime
时,Joda-Time只是假设它处于JVM默认时区。
如果你知道输入是UTC,但输入本身没有关于它的信息,你必须告诉它。一种方法是在格式化设置:
// set the formatter to UTC
DateTimeFormatter inputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS")
.withZone(DateTimeZone.UTC);
// DateTime will be in UTC
DateTime parsed = inputFormatter.parseDateTime("2017-09-16T05:06:18.157");
另一种替代方法是,首先解析输入到org.joda.time.LocalDateTime
(表示日期和时间没有时区的一类),然后将其转换为DateTime
在UTC :
// parse to LocalDateTime
DateTime = parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
// convert to a DateTime in UTC
.toDateTime(DateTimeZone.UTC);
两者产生相同的DateTime
,对应于UTC 2017-09-16T05:06:18.157Z
。
格式化为“IST时区”(这其实并不是一个时区 - 低于更多),你还可以设置在格式化的时区:
// convert to Asia/Kolkata
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss")
.withZone(DateTimeZone.forID("Asia/Kolkata"));
System.out.println(outputFormatter.print(parsed));
或者你可以转换DateTime
到另一个时区,使用withZone()
method:
DateTimeFormatter outputFormatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss");
// convert to Asia/Kolkata
System.out.println(outputFormatter.print(parsed.withZone(DateTimeZone.forID("Asia/Kolkata"))));
双方将打印:
2017年9月16日10点36分18秒
在你的代码正在使用DateTimeZone.getDefault()
,是可以获得JVM默认时区(有一些tricky details)。但默认时区为can be changed without notice, even at runtime,所以最好指定要使用哪一个。
另外,请记住,像IST这样的短名称不是实时时区。始终优先使用IANA timezones names(始终采用Region/City
的格式,如Asia/Kolkata
或Europe/Berlin
)。
避免使用3个字母的缩写(如IST
或),因为它们是ambiguous and not standard。请检查this list IST可以是“印度标准时间”,“以色列标准时间”和“爱尔兰标准时间”。
您可以通过调用DateTimeZone.getAvailableIDs()
来获得可用时区列表(并选择最适合您系统的时区)。
新的Java日期/时间API
乔达时间是在修的模式,正在被新的API所取代,所以我不建议开始使用它的新项目。即使在joda's website中也写道:“请注意,Joda-Time被认为是一个大部分已完成的项目,没有计划任何重大改进,如果使用Java SE 8,请迁移到java.time(JSR-310)。。
如果您不能(或不想)从Joda-Time迁移到新的API,则可以忽略此部分。
在Android中,您可以使用ThreeTen Backport,它是Java 8新日期/时间类的一个很好的后端。要使其工作,您还需要ThreeTenABP(更多关于如何使用它here)。
这个新的API有lots of different date/time types每种情况。
首先,您可以将输入解析为org.threeten.bp.LocalDateTime
,然后我使用org.threeten.bp.ZoneOffset
将其转换为UTC,结果为org.threeten.bp.OffsetDateTime
。
然后,我用一个org.threeten.bp.ZoneId
将其转换为另一个时区,并使用org.threeten.bp.format.DateTimeFormatter
对其进行格式化(这基本上是什么的@Ole V.V's comment建议 - 只是为了显示它是多么简单,因为有没有什么太多的不同做):
// parse to LocalDateTime
OffsetDateTime parsed = LocalDateTime.parse("2017-09-16T05:06:18.157")
// convert to UTC
.atOffset(ZoneOffset.UTC);
// convert to Asia/Kolkata
ZoneId zone = ZoneId.of("Asia/Kolkata");
DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
System.out.println(outputFormatter.format(parsed.atZoneSameInstant(zone)));
输出是:
2017年9月16日10点36分18秒
欢迎至S大头钉溢出。请注意,堆栈溢出不能替代您的搜索引擎。这个问题已经被问了很多次,你的搜索引擎会更快地找到你的答案。 –
Joda-Time是(我所知道的)比发布在这个答案中的过时SimpleDateFormat更好。最好是[ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP)。 –
您的时间戳字符串符合ISO 8601格式,我认为Joda-Time和ThreeTenABP当然可以理解为它们的默认格式,因此您不需要明确的格式化程序进行分析。 –