有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java转换ldap日期

我正在以编程方式从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");

将显示错误的日期,因为它忽略了时区的日期

有没有直接转换的方法


共 (6) 个答案

  1. # 1 楼答案

    您可以使用org的方法。阿帕奇。目录共享。ldap。util。日期:

    String ldapDate="20090813145607.0Z";

    Date date = DateUtils.parse(ldapDate);

    String generalizedTime = DateUtils.getGeneralizedTime(date);

  2. # 2 楼答案

    ISO 8601

    正如前面提到的两个其他答案一样,所讨论的日期时间格式由RFC 4517 Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules定义。参见第3.3.13节,广义时间

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

    在这些格式中,末尾的ZZulu的缩写,表示UTC(基本上与GMT相同)

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

    爪哇。时间

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

    现在在maintenance mode中,Joda-Time项目还建议迁移到java。时间

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

    java的大部分内容。时间功能被向后移植到Java6&;7 inThreeTen-Backport,并进一步适应Android inThreeTenABP

    {a10}项目扩展了java。额外上课的时间。这个项目是将来可能添加到java的一个试验场。时间

    解析

    定义适合RFC 4517的格式化模式。研究模式编码的^{}类。这应该有效:uuuuMMddHHmmss[,S][.S]X。方括号表示可选。我们可以使用点或逗号。请注意秒分数的单数数字。末尾的X允许使用Zoffset-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的代码,以防出现意外输入

  3. # 3 楼答案

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

    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;
            }
    
  4. # 4 楼答案

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

    String[] parts = inputDateTime.split("[.]");
    String dateTimePart = parts[0];
    String timeZonePart = "+0" + parts[1].substring(0, parts[1].length() - 1) + "00";
    SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmssZ");
    Date theDate = sdf.parse(dateTimePart + timeZonePart);
    
  5. # 5 楼答案

    检查上面提到的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;
    }
    
  6. # 6 楼答案

    该属性的语法在目录模式中描述。在转换、比较和排序从目录检索或存储在目录中的数据时,应用程序必须使用架构。如果whenCreated属性的语法为generalizedTime,则应用程序在转换时必须使用库以获得通用时间。泛化时间的语法在RFC4517中描述