我有 SimpleDateFormat 构造函数
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
我正在解析字符串"2013-09-29T18:46:19Z".
我读过这里 Z 代表GMT/UTC
时区。但是当我在控制台上打印这个日期时,它会为返回的日期打印 IST timezne。
现在我的问题是我的输出是对还是错?
我有 SimpleDateFormat 构造函数
SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'")
我正在解析字符串"2013-09-29T18:46:19Z".
我读过这里 Z 代表GMT/UTC
时区。但是当我在控制台上打印这个日期时,它会为返回的日期打印 IST timezne。
现在我的问题是我的输出是对还是错?
您尚未设置时区,仅Z
在日期/时间的末尾添加了 a,因此它看起来像 GMT 日期/时间,但这不会更改值。
将时区设置为 GMT,它将是正确的。
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
'T'
并且'Z'
在这里被视为常数。您需要在Z
没有引号的情况下通过。此外,您需要在输入字符串中指定时区。
示例:2013-09-29T18:46:19-0700
格式为"yyyy-MM-dd'T'HH:mm:ssZ"
从 ISO 8601 字符串到 Java 日期对象
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
sdf.parse("2013-09-29T18:46:19Z"); //prints-> Mon Sep 30 02:46:19 CST 2013
如果你不设置TimeZone.getTimeZone("GMT")
那么它会输出Sun Sep 29 18:46:19 CST 2013
从 Java 日期对象到 ISO 8601 字符串
并将对象转换Date
为 ISO 8601 标准 ( yyyy-MM-dd'T'HH:mm:ss'Z'
) 使用以下代码
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US);
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
System.out.println(sdf.format(new Date())); //-prints-> 2015-01-22T03:23:26Z
另请注意,没有' '
在 Zyyyy-MM-dd'T'HH:mm:ssZ
打印2015-01-22T03:41:02+0000
如果您想处理 Date 的“标准”JSON 表示,那么最好使用此模式:"yyyy-MM-dd'T'HH:mm:ssX"
.
注意X
最后。 它将处理 ISO 8601 标准中的时区,而 ISO 8601 正是在 Javascript 中产生此语句的原因new Date().toJSON()
与其他答案相比,它有一些好处:
sdf.setTimeZone(TimeZone.getTimeZone("GMT"));
从 Java 8 开始,其他答案已过时。
Instant // Represent a moment in UTC.
.parse( "2013-09-29T18:46:19Z" ) // Parse text in standard ISO 8601 format where the `Z` means UTC, pronounces “Zulu”.
.atZone( // Adjust from UTC to a time zone.
ZoneId.of( "Asia/Kolkata" )
) // Returns a `ZonedDateTime` object.
您的字符串格式恰好符合ISO 8601标准。该标准定义了将各种日期时间值表示为文本的合理格式。
旧的java.util.Date
/.Calendar
和java.text.SimpleDateFormat
类已被 Java 8 及更高版本中内置的 java.time 框架所取代。请参阅教程。避免使用旧类,因为它们已被证明设计不佳、令人困惑且麻烦。
旧类中的部分糟糕设计让您感到厌烦,该toString
方法在生成实际为 UTC (GMT) 的日期时间值的文本表示时应用了 JVM 的当前默认时区;善意但令人困惑。
java.time 类在解析/生成日期时间值的文本表示时默认使用 ISO 8601 格式。所以不需要指定解析模式。
Instant instant = Instant.parse( "2013-09-29T18:46:19Z" );
您可以根据需要应用时区来生成ZonedDateTime
对象。
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = instant.atZone( zoneId );
如果您没有继续使用 java8 的选项,最好使用 'yyyy-MM-dd'T'HH:mm:ssX XX ',因为它会再次正确解析(虽然只有一个 X,但情况可能并非如此。 ..取决于您的解析功能)
X 生成:+01
XXX 生成:+01:00
'Z'
不一样Z
'Z'
只是一个字符文字,而是零时区偏移Z
的时区指示符。它代表 Zulu 并指定Etc/UTC
时区(时区偏移量为+00:00
小时)。
因此,请勿使用'Z'
in 模式进行解析/格式化。
java.time
现代日期时间 API现代日期时间 API 基于ISO 8601DateTimeFormatter
,只要日期时间字符串符合 ISO 8601 标准,就不需要明确使用对象。日期时间字符串2013-09-29T18:46:19Z
符合 ISO 8601 标准。
演示:
import java.time.Instant;
import java.time.OffsetDateTime;
import java.time.ZonedDateTime;
public class Main {
public static void main(String[] args) {
Instant instant = Instant.parse("2013-09-29T18:46:19Z");
OffsetDateTime odt = OffsetDateTime.parse("2013-09-29T18:46:19Z");
ZonedDateTime zdt = ZonedDateTime.parse("2013-09-29T18:46:19Z");
System.out.println(instant);
System.out.println(odt);
System.out.println(zdt);
}
}
输出:
2013-09-29T18:46:19Z
2013-09-29T18:46:19Z
2013-09-29T18:46:19Z
An代表UTCInstant
时间线上的一个瞬时点。输出中的 是零时区偏移的时区指示符。它代表 Zulu 并指定时区(时区偏移量为小时)。Z
Etc/UTC
+00:00
注意#1:如果您需要找出Instant
特定时区中的日期和时间,您可以使用Instant#atZone
例如以下代码将Instant
在印度打印日期和时间:
ZonedDateTime zdtIndia = instant.atZone(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtIndia);
您甚至可以使用例如以下代码将对象ZonedDateTime
从一个时区转换为另一个时区将转换为表示印度日期和时间的对象:ZonedDateTime#withZoneSameInstant
zdt
ZonedDateTime
ZonedDateTime zdtIndia = zdt.withZoneSameInstant(ZoneId.of("Asia/Kolkata"));
System.out.println(zdtIndia);
注意#2:无论出于何种原因,如果您需要将此对象转换Instant
为 的对象java.util.Date
,您可以执行以下操作:
Date date = Date.from(instant);
您甚至可以将OffsetDateTime
和的对象转换ZonedDateTime
为 的对象java.util.Date
,如下所示:
Date date = Date.from(odt.toInstant());
&
Date date = Date.from(zdt.toInstant());
从Trail: Date Time了解有关现代日期时间 API *的更多信息。
java.util.Date
对象打印印度日期和时间?java.util.Date
对象仅表示自称为“纪元”的标准基准时间(即 1970 年 1 月 1 日 00:00:00 GMT(或 UTC)以来的毫秒数)。由于它不保存任何时区信息,因此它的函数应用 JVM 的时区以从该毫秒值派生的格式toString
返回 a 。要以不同的格式和时区表示对象,您需要使用所需的格式和适用的时区,例如String
EEE MMM dd HH:mm:ss zzz yyyy
String
java.util.Date
SimpleDateFormat
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
String strDate = sdf.format(date);
System.out.println(strDate);
演示:
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 {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssXXX", Locale.ENGLISH);
Date date = sdf.parse("2013-09-29T18:46:19Z");
// In JVM's timezone and default format as returned by Date#toString
System.out.println(date);
// In UTC and custom format
sdf.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
String strDate = sdf.format(date);
System.out.println(strDate);
// In India and custom format
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Kolkata"));
strDate = sdf.format(date);
System.out.println(strDate);
}
}
输出(我的时区是欧洲/伦敦):
Sun Sep 29 19:46:19 BST 2013
2013-09-29T18:46:19Z
2013-09-30T00:16:19+05:30
* 出于任何原因,如果您必须坚持使用 Java 6 或 Java 7,则可以使用ThreeTen-Backport,它将大部分java.time功能向后移植到 Java 6 和 7。如果您正在为 Android 项目和 Android API 工作level 仍然不符合 Java-8,请检查Java 8+ APIs available through desugaring和How to use ThreeTenABP in Android Project。
对于 Java 8:
您可以使用 inbuiltjava.time.format.DateTimeFormatter
来减少任何拼写错误的机会,例如
DateTimeFormatter formatter = DateTimeFormatter.ISO_ZONED_DATE_TIME;
ISO_ZONED_DATE_TIME 表示2011-12-03T10:15:30+01:00[Europe/Paris]
是 Oracle 提供的捆绑标准 DateTime 格式之一链接