我正在以编程方式从 ldap 导出用户。因此,我正在从 ldap 检索用户。其中一个属性是 whenCreated
。
我必须转换的值之一是:20090813145607.0Z
直接拆分它我得到以下格式:yyyyMMddHHmmss
+.0Z
.问题是应用程序在 CET 时区中运行,并且存储的时间是 UTC,这可能由 .0Z
指示。它是 14:56 UTC
,本地表示是 16:56
。夏季时间似乎为 2 小时,冬季时间为 1 小时。
我检查了 SimpleDateFormat 并且有一个时区占位符,但它的格式不同。
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
sdf.parse("20090813145607.0Z");
将显示错误的日期,因为它忽略了日期时区。
有没有办法直接转换呢?
最佳答案
ISO 8601
正如提到的其他几个答案,所讨论的日期时间格式由 RFC 4517 Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules 定义。请参阅第 3.3.13 节,通用时间。
该部分解释了此 LDAP 格式是 ISO 8601 定义的一种日期时间格式的受限版本。这种使用最少分隔符的样式在 ISO 8601 中称为“基本”。
在这些格式中,末尾的 Z
是 Zulu
的缩写,表示 UTC(与 GMT 基本相同)。
小数点和末尾的数字代表秒的分数。请注意,在 RFC 4517 和 ISO 8601 中都可以用逗号代替点(句点)。在 ISO 8601 中,实际上建议在点上使用逗号。RFC 4517 规范仅允许单个数字分数(分数的十分之几) ) 或根本没有点/逗号和数字。请注意,相比之下:(a) ISO 8601 允许任意数量的小数位,并且 (b) java.time 对象具有纳秒分辨率,最多可容纳九位小数秒。
java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了旧的麻烦的日期时间类,例如 java.util.Date
、.Calendar
和 java.text.SimpleDateFormat
。
现在在 maintenance mode 中,Joda-Time 项目还建议迁移到 java.time。
要了解更多信息,请参阅 Oracle Tutorial 。并在 Stack Overflow 中搜索许多示例和解释。
许多 java.time 功能在 ThreeTen-Backport 中向后移植到 Java 6 和 7,并在 ThreeTenABP 中进一步适应 Android。
ThreeTen-Extra 项目用附加类扩展了 java.time。该项目是 future 可能添加到 java.time 的试验场。
解析
定义格式模式以适应 RFC 4517。研究模式编码的 DateTimeFormatter
类。这应该有效:uuuuMMddHHmmss[,S][.S]X
。方括号表示可选。我们容纳一个点或逗号。注意秒的小数部分的单数。末尾的 X
允许 Z
或 offset-from-UTC,例如 -08 或 -0830 或 -08:30 或 -083015 或 -08:30:15。
String input = "20090813145607.0Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "uuuuMMddHHmmss[,S][.S]X" );
OffsetDateTime odt = OffsetDateTime.parse ( input , f );
Instant instant = odt.toInstant ();
转储到控制台。
System.out.println ( "input: " + input + " | odt: " + odt + " | instant: " + instant );
input: 20090813145607.0Z | odt: 2009-08-13T14:56:07Z | instant: 2009-08-13T14:56:07Z
当然,您还应该为 java.time.format.DateTimeParseException
编写代码检查,以防出现意外输入。
关于java - 转换 ldap 日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9806329/