转换 ldap 日期

2022-01-17 00:00:00 ldap java

我正在以编程方式从 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 定义轻量级目录访问协议 (LDAP):语法和匹配规则.请参阅第 3.3.13 节,广义时间.

该部分说明此 LDAP 格式是 ISO 8601 定义的日期时间格式之一的受限版本.这种使用最少分隔符的样式在 ISO 8601 中被称为基本".

在这些格式中,末尾的 ZZulu 的缩写,意思是 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.

现在在 维护模式,Joda-Time 项目还建议迁移到 java.time.

要了解更多信息,请参阅 Oracle 教程.并在 Stack Overflow 上搜索许多示例和解释.

大部分 java.time 功能都向后移植到 Java 6 &7 在 ThreeTen-Backport 并在 ThreeTenABP.

ThreeTen-Extra 项目通过附加类扩展了 java.time.该项目是未来可能添加到 java.time 的试验场.

解析

定义格式模式以适应 RFC 4517.研究 DateTimeFormatter 类用于模式编码.这应该可以工作:uuuuMMddHHmmss[,S][.S]X.方括号表示可选.我们可以容纳点或逗号.注意秒的小数部分的单数.末尾的 X 允许使用 Z 或 offset-from-UTC 例如 -08 或 -0830 或 -08:30 或 -083015 或 -08:30:15.

字符串输入=20090813145607.0Z";DateTimeFormatter f = DateTimeFormatter.ofPattern ("uuuuMMddHHmmss[,S][.S]X");OffsetDateTime odt = OffsetDateTime.parse ( 输入 , f );Instant Instant = odt.toInstant ();

转储到控制台.

System.out.println("输入:"+输入+"|odt:"+odt+"|instant:"+instant);

<块引用>

输入:20090813145607.0Z |odt: 2009-08-13T14:56:07Z |瞬间:2009-08-13T14:56:07Z

当然,您还应该编写代码检查 java.time.format.DateTimeParseException 以防意外输入.

I'm exporting users from an ldap programmatically. Therefor I'm retrieving the users from ldap. One of the attributes is whenCreated.

One of the values I have to convert is: 20090813145607.0Z Directly splitting it up I get the following format: yyyyMMddHHmmss+.0Z. The problem is that the application is running in CET timezone and the time stored is UTC which is probably indicated by the .0Z . It is 14:56 UTC and the local representation is 16:56. For summer time it seems to be 2 hours and for winter time 1 hour.

I checked the SimpleDateFormat and there is a placeholder for the timezone, however its a different format.

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
sdf.parse("20090813145607.0Z");

Will show the wrong date as it ignores the dates time zone.

Is there a way to convert it directly?

解决方案

ISO 8601

As a couple of other Answers mentioned, the date-time format in question is defined by RFC 4517 Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules. See section 3.3.13, Generalized Time.

That section explains this LDAP format is a restricted version of one of the date-time formats defined by ISO 8601. This style using a minimum of separators is known as "basic" in ISO 8601.

In these formats, the Z on the end is short for Zulu and means UTC (basically same as GMT).

The decimal point and digit at the end represents a fraction of a second. Note that a comma is possible instead of the dot (period) in both RFC 4517 and ISO 8601. The comma is actually recommended over the dot in ISO 8601. The RFC 4517 spec allows for only a single digit fraction (some tenths of a fraction) or no dot/comma & digit at all. Note that in contrast: (a) ISO 8601 allows for any number of fractional digits, and (b) java.time objects have nanosecond resolution for up to nine digits of fractional second.

java.time

The java.time framework is built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date, .Calendar, & java.text.SimpleDateFormat.

Now in maintenance mode, the Joda-Time project also advises migration to java.time.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations.

Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP.

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time.

Parsing

Define a formatting pattern to fit RFC 4517. Study the DateTimeFormatter class for the pattern coding. This should work: uuuuMMddHHmmss[,S][.S]X. The square brackets mean optional. We accommodate either a dot or comma. Note the singular digit for fraction of second. The X on the end allows for either a Z or an offset-from-UTC such as -08 or -0830 or -08:30 or -083015 or -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 ();

Dump to console.

System.out.println ( "input: " + input + " | odt: " + odt + " | instant: " + instant );

input: 20090813145607.0Z | odt: 2009-08-13T14:56:07Z | instant: 2009-08-13T14:56:07Z

Of course you should also be coding a check for java.time.format.DateTimeParseException in case of unexpected input.

相关文章