java.util.Date
对象只是表示自“纪元”即1970年1月1日00:00:00 GMT(或UTC)以来的毫秒数。因为它没有保存任何时区信息,所以其toString
函数应用JVM的时区返回一个格式为EEE MMM dd HH:mm:ss zzz yyyy
的String
,该格式派生自这个毫秒数值。如果需要在不同的时区中以不同的格式获取java.util.Date
对象的String
表示形式,则需要使用带有所需格式和适用时区的SimpleDateFormat
。
除此之外,您的代码还存在一些问题:
- 使用24小时制时,应该使用大写字母
H
而不是小写字母h
。小写字母h
用于12小时制(即带有AM/PM标记)。
- 尽管
SimpleDateFormat
可以使用MMM
解析月份的长名称(例如January),但它实际上是用于3个字母的月份名称(例如Jan)。如果您尝试使用现代日期时间API进行操作,则会收到DateTimeParseException
的错误提示。您应该使用MMMM
来获取月份的长名称。
演示结合这些要点:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
public class Main {
public static void main(String[] args) throws ParseException {
String strDateTime = "31 October 2011 11:19:56 GMT";
SimpleDateFormat sdf = new SimpleDateFormat("dd MMMM yyyy HH:mm:ss z", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
Date date = sdf.parse(strDateTime);
String strDate = sdf.format(date);
System.out.println(strDate);
sdf = new SimpleDateFormat("MMMM dd HH:mm:ss z yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
strDate = sdf.format(date);
System.out.println(strDate);
sdf.setTimeZone(TimeZone.getTimeZone("America/New_York"));
strDate = sdf.format(date);
System.out.println(strDate);
}
}
输出:
31 October 2011 11:19:56 GMT
October 31 11:19:56 GMT 2011
October 31 07:19:56 EDT 2011
在线演示
切换到 java.time
API。
java.util
日期时间API及其格式化API SimpleDateFormat
已过时且容易出错。建议完全停止使用它们并切换到现代日期时间API*。
使用现代日期时间API java.time
的解决方案:
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
String strDateTime = "31 October 2011 11:19:56 GMT";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("dd MMMM uuuu HH:mm:ss z", Locale.ENGLISH);
ZonedDateTime zdt = ZonedDateTime.parse(strDateTime, dtf);
System.out.println(zdt);
DateTimeFormatter dtfAnother = DateTimeFormatter.ofPattern("MMMM dd HH:mm:ss z uuuu", Locale.ENGLISH);
String strDate = dtfAnother.format(zdt);
System.out.println(strDate);
}
}
输出:
2011-10-31T11:19:56Z[GMT]
October 31 11:19:56 GMT 2011
在线演示
输出中的Z
是零时区偏移的时区标识符。它代表Zulu并指定Etc/UTC
时区(其时区偏移为+00:00
小时)。
从教程:日期时间了解更多关于现代日期时间API的内容。
* 如果由于任何原因,您必须坚持使用Java 6或Java 7,您可以使用ThreeTen-Backport将大多数java.time功能移植到Java 6和7。如果您正在为Android项目工作,并且您的Android API级别仍不符合Java-8,请查看通过解糖可用的Java 8+ API和如何在Android项目中使用ThreeTenABP。