web-dev-qa-db-ja.com

LDAP日付の変換

私はプログラムでLDAPからユーザーをエクスポートしています。そのため、LDAPからユーザーを取得しています。属性の1つはwhenCreatedです。

変換する必要のある値の1つは次のとおりです。20090813145607.0Z直接分割すると、次の形式になります:yyyyMMddHHmmss + .0Z。問題は、アプリケーションがCETタイムゾーンで実行されており、保存されている時刻がUTCであるということです。これは、おそらく.0Zで示されます。それは14:56 UTCであり、ローカル表現は16:56です。夏は2時間、冬は1時間のようです。

SimpleDateFormat を確認しました。タイムゾーンのプレースホルダーがありますが、形式が異なります。

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

日付のタイムゾーンを無視するため、間違った日付が表示されます。

直接変換する方法はありますか?

16
Udo Held

上記で説明した分割を使用してから、_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);
_
8

上記のRFCを確認すると、LDAP日付のデフォルトの動作としてUTCを使用することが推奨されているようです。そのため、私はそれを直接変換しました:

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;
}
8
Udo Held

属性の構文は、ディレクトリスキーマに記述されています。アプリケーションは、ディレクトリから取得またはディレクトリに保存されたデータを変換、比較、および順序付けするときにスキーマを使用する必要があります。 whenCreated属性の構文がgeneralizedTimeの場合、アプリケーションは変換時に一般化された時間ライブラリを使用する必要があります。 generalizedTimeの構文は、 RFC4517 で説明されています。

3
Terry Gardner

Org.Apache.directory.shared.ldap.util.DateUtilsのメソッドを使用できます。

文字列ldapDate = "20090813145607.0Z";

日付日付= DateUtils.parse(ldapDate);

文字列generalizedTime = DateUtils.getGeneralizedTime(date);

3
iberck

これはのみ私のために働いたコードの一部です:

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;
        }
2
kylexy1357

Apache util GeneralizedTimeクラスを使用しようとしました http://directory.Apache.org/api/gen-docs/1.0.0-M11/apidocs/org/Apache/directory/shared/util/GeneralizedTime.html 結果がまちまち

現在の時刻からActiveDirecotry形式に変換するには:

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」が表示されるので、秒の前に「.0」を挿入します。これがあなたがしなければならないことです(私の場合、私は分数を気にしないのでゼロを入れます。ADは気にします)

GeneralizedTime gt = new GeneralizedTime(Calendar.getInstance());
String gtADString = gt.toGeneralizedTime(GeneralizedTime.Format.YEAR_MONTH_DAY_HOUR_MIN_SEC, GeneralizedTime.FractionDelimiter.DOT, 1, GeneralizedTime.TimeZoneFormat.Z).replaceFirst("Z", "\\.0Z");

ちなみに、このコードはADGeneralizedTime文字列形式からJava Date)に変換されます

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