Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/364.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 转换ldap日期_Java_Ldap - Fatal编程技术网

Java 转换ldap日期

Java 转换ldap日期,java,ldap,Java,Ldap,我正在以编程方式从ldap导出用户。因此,我正在从ldap检索用户。当创建时,其中一个属性是 我必须转换的一个值是:20090813145607.0Z直接将其拆分,得到以下格式:yyymmddhhmmss+.0Z。问题是应用程序在CET时区运行,存储的时间是UTC,可能由.0Z指示。它是14:56 UTC,本地表示为16:56。对于夏季,似乎是2小时,而对于冬季,则是1小时 我检查了,有一个时区占位符,但它的格式不同 SimpleDateFormat sdf = new SimpleDateFo

我正在以编程方式从ldap导出用户。因此,我正在从ldap检索用户。当创建时,其中一个属性是

我必须转换的一个值是:
20090813145607.0Z
直接将其拆分,得到以下格式:
yyymmddhhmmss
+
.0Z
。问题是应用程序在CET时区运行,存储的时间是UTC,可能由
.0Z
指示。它是
14:56 UTC
,本地表示为
16:56
。对于夏季,似乎是2小时,而对于冬季,则是1小时

我检查了,有一个时区占位符,但它的格式不同

SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
sdf.parse("20090813145607.0Z");
将显示错误的日期,因为它忽略了时区的日期


有没有直接转换的方法?

使用上面描述的分割,然后将
0Z
时区重新格式化为标准格式,然后使用
sdf.parse(…)
?可能是这样(当然,添加了适当的错误检查):

String[]parts=inputDateTime.split(“[.]”);
字符串dateTimePart=parts[0];
字符串timeZonePart=“+0”+部分[1]。子字符串(0,部分[1]。长度()-1)+“00”;
SimpleDataFormat sdf=新的SimpleDataFormat(“yyyyMMddHHmmssZ”);
Date theDate=sdf.parse(dateTimePart+timeZonePart);

目录架构中描述了属性的语法。在转换、比较和排序从目录检索或存储在目录中的数据时,应用程序必须使用架构。如果
whenCreated
属性的语法为
generalizedTime
,则应用程序在转换时必须使用库来表示广义时间。泛化时间的语法如中所述。

检查上述RFC似乎使用UTC是ldap日期的推荐默认行为。因此,我直接将其转换为:

public Date parseLdapDate(String ldapDate){
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
    sdf.setTimeZone(TimeZone.getTimeZone("GMT"));

    try {
        return sdf.parse(ldapDate);
    } catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return null;
}

我尝试使用apache util GeneratedTime类,但结果不一

要将当前时间转换为活动目录格式,请执行以下操作:

GeneralizedTime gt = new GeneralizedTime(Calendar.getInstance());
String gtADString = gt.toGeneralizedTime(GeneralizedTime.Format.YEAR_MONTH_DAY_HOUR_MIN_SEC_FRACTION, GeneralizedTime.FractionDelimiter.DOT, 1, GeneralizedTime.TimeZoneFormat.Z).replaceFirst("Z", "\\.0Z");
唯一的问题是它不能像广告宣传的那样工作。根据这个调用,点后面的分数部分的长度应该是“1”,但结果仍然是3。我得到的不是“20120410011958.6Z”,而是“20120410011958.687Z”,因此我仍然需要以秒为单位获取时间,并在Z之前插入“.0”。因此,您必须做的是(在我的情况下,我不关心分数,所以我将其置为零。AD关心)

顺便说一下,这段代码将AD GeneratedTime字符串格式转换为Java日期

 GeneralizedTime gt = new GeneralizedTime(str);
 Date d = gt.getCalendar().getTime();

您可以使用org.apache.directory.shared.ldap.util.DateUtils的方法:

字符串ldapDate=“20090813145607.0Z”

Date-Date=DateUtils.parse(ldapDate)

字符串generalizedTime=DateUtils.getGeneralizedTime(日期)

ISO 8601 正如前面提到的两个其他答案一样,所讨论的日期时间格式由定义。见第3.3.13节,广义时间

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

在这些格式中,末尾的
Z
Zulu
的缩写,意思是(与GMT基本相同)

小数点和末尾的数字表示秒的小数点。注意,在RFC 4517和ISO 8601中,逗号可以代替点(句点)。在ISO 8601中,实际上建议使用逗号代替圆点。RFC4517规范只允许一个位数的分数(分数的十分之一)或根本不允许点/逗号和数字。请注意,与此相反:(a)ISO 8601允许任何数量的小数位数,(b)java.time对象的分辨率为纳秒,最高可达九位数的小数秒

java.time 该框架内置于Java8及更高版本中。这些类取代了旧的麻烦的日期时间类,如
java.util.date
.Calendar
,&
java.text.SimpleDateFormat

现在,该项目还建议迁移到java.time

要了解更多信息,请参阅。并搜索堆栈溢出以获得许多示例和解释

大部分java.time功能都在中向后移植到Java6和Java7,并在中进一步适应Android

该项目使用其他类扩展了java.time。这个项目是java.time将来可能添加的一个试验场

解析 定义适合RFC 4517的格式化模式。学习模式编码的课程。这应该有效:
uummdhhmmss[,S][.S]X
。方括号表示可选。我们可以使用点或逗号。请注意秒分数的单数数字。末端的
X
允许使用
Z
或-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 );
输入:20090813145607.0Z | odt:2009-08-13T14:56:07Z |瞬间:2009-08-13T14:56:07Z


当然,您还应该编写一个检查
java.time.format.DateTimeParseException
,以防出现意外输入。

这是唯一对我有效的代码:

static String parseLdapDate(String ldapDate) {

            long nanoseconds = Long.parseLong(ldapDate);   // nanoseconds since target time that you want to convert to java.util.Date

            long mills = (nanoseconds / 10000000);

            long unix = (((1970 - 1601) * 365) - 3 + Math.round((1970 - 1601) / 4)) * 86400L;

            long timeStamp = mills - unix;

            Date date = new Date(timeStamp * 1000L); // *1000 is to convert seconds to milliseconds
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); // the format of your date
    //sdf.setTimeZone(TimeZone.getTimeZone("GMT")); // give a timezone reference for formating (see comment at the bottom
            String formattedDate = sdf.format(date);

            return  formattedDate;
        }

我不确定
.0Z
的确切含义是什么,由于日期来自ldap,我不知道它将来是否会改变。我不知道还有什么需要exspect,但是它应该是一个ldap标准,并且符合其中一个RFC。不,“.0”与时区无关。“Z”表示祖鲁(UTC)时间——故事的结尾。秒后的“.0”表示十进制秒。所以午后59.5秒可能看起来像“yyyymmdd120059.5Z”。有关更多详细信息,请参阅@Basil Borrque在下面给出的“ISO 8601”答案。感谢您提供的信息。你知道这样的库或内置方法吗?
static String parseLdapDate(String ldapDate) {

            long nanoseconds = Long.parseLong(ldapDate);   // nanoseconds since target time that you want to convert to java.util.Date

            long mills = (nanoseconds / 10000000);

            long unix = (((1970 - 1601) * 365) - 3 + Math.round((1970 - 1601) / 4)) * 86400L;

            long timeStamp = mills - unix;

            Date date = new Date(timeStamp * 1000L); // *1000 is to convert seconds to milliseconds
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); // the format of your date
    //sdf.setTimeZone(TimeZone.getTimeZone("GMT")); // give a timezone reference for formating (see comment at the bottom
            String formattedDate = sdf.format(date);

            return  formattedDate;
        }