2012-03-21 13 views
5

Eksportuję użytkowników z programu ldap programowo. W związku z tym pobieram użytkowników z ldap. Jednym z atrybutów jest whenCreated.Konwertowanie daty ldap

Jedna z wartości, którą muszę przekonwertować, to: 20090813145607.0Z Bezpośrednio dzieląc ją otrzymuję następujący format: yyyyMMddHHmmss + .0Z. Problem polega na tym, że aplikacja działa w strefie czasowej CET, a przechowywany czas to UTC, który prawdopodobnie jest oznaczony przez .0Z. Jest to 14:56 UTC, a lokalna reprezentacja to 16:56. Czas letni wynosi 2 godziny, a zimą 1 godzinę.

Sprawdziłem SimpleDateFormat i tam jest miejsce na strefę czasową, jednak jest to inny format.

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

Pokaże błędną datę, ponieważ ignoruje strefę czasową dat.

Czy istnieje sposób na konwersję bezpośrednio?

Odpowiedz

5

Co za pomocą split ty opisanej powyżej, a następnie sformatowanie czasową 0Z do standardowego formatu, a następnie za pomocą sdf.parse(...)? Może coś w tym stylu (oczywiście z dodatkowym sprawdzaniem błędów):

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); 
+0

Nie jestem pewien, co dokładne znaczenie '.0Z' jest i jak data jest pochodzący z I don LDAP nie wiem, czy to może się zmienić w przyszłości. Nie wiedziałbym, co jeszcze można przetestować, jednak powinien to być standard LDAP i być zgodny z jednym z programów rfcs. http://msdn.microsoft.com/en-us/library/windows/desktop/ms680924%28v=vs.85%29.aspx –

+0

NOPE - ".0" nie ma nic wspólnego ze strefą czasową. "Z" oznacza czas Zulu (UTC) - koniec historii. ".0" po sekundach oznacza sekundy dziesiętne. A więc pięćdziesiąt dziewięć i pół sekundy po południu może wyglądać jak "yyyymmdd120059.5Z". Zobacz odpowiedź "ISO 8601" poniżej @Basil Borrque, aby uzyskać więcej szczegółów. –

2

Składnię atrybutu opisano w schemacie katalogów. Aplikacje muszą używać schematu podczas konwersji, porównywania i porządkowania danych pobranych z katalogu lub zapisanych w tym katalogu. Jeśli składnia atrybutu to generalizedTime, aplikacje muszą używać bibliotek do uogólnionego czasu podczas konwersji. Składnia generalizedTime jest opisana w RFC4517.

+1

Dzięki za informację. Czy znasz taką bibliotekę lub jakąś wbudowaną metodę? –

6

Sprawdzanie RFC, o którym mowa powyżej, wydaje się być użycie UTC jest zalecanym domyślnym zachowaniem dla dat ldap. Przeto ja konwertowane bezpośrednio:

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; 
} 
0

Próbowałem użyć apache util GeneralizedTime klasy http://directory.apache.org/api/gen-docs/1.0.0-M11/apidocs/org/apache/directory/shared/util/GeneralizedTime.html z mieszanymi wynikami

przekonwertować z aktualnym czasem Active formacie Direcotry:

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"); 

Jedyny problem jest to, że nie działa tak jak w reklamie. Długość części ułamkowej po kropce ma wynosić "1" zgodnie z tym wywołaniem, ale wynik jest nadal wyświetlany jako 3. Zamiast "20120410011958.6Z" otrzymuję "20120410011958.687Z", więc wciąż muszę znaleźć czas sekund i włóż”.0" przed Z. więc oto co trzeba zrobić (w moim przypadku nie dbam o frakcji więc umieścić zero. AD dba)

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"); 

Nawiasem mówiąc ten kod konwertuje z AD GeneralizedTime format string Java Data

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

można użyć metod org.apache.directory.shared.ldap.util.DateUtils:

String ldapDate = "20090813145607.0Z";

Data daty = DateUtils.parsować (ldapDate);

Łańcuch generalizedTime = DateUtils.getGeneralizedTime (data);

4

ISO 8601

Jak kilka innych odpowiedzi wymienionych, format daty i godziny w pytaniu jest zdefiniowany przez RFC 4517 Lightweight Directory Access Protocol (LDAP): Syntaxes and Matching Rules. Patrz sekcja 3.3.13, Czas ogólny.

W tej sekcji wyjaśniono, że ten format LDAP jest ograniczoną wersją jednego z formatów daty i czasu zdefiniowanego przez ISO 8601. Ten styl używając minimum separatorów jest znany jako „podstawowe” w ISO 8601.

W tych formatów The Z na końcu jest skrótem Zulu i oznacza UTC (w zasadzie taki sam jak GMT).

Kropka dziesiętna i cyfra na końcu reprezentują ułamek sekundy. Zauważ, że zamiast kropki (kropki) możliwy jest przecinek zarówno w RFC 4517, jak i ISO 8601. Przecinek jest rzeczywiście zalecany do kropki w ISO 8601. Specyfikacja RFC 4517 dopuszcza tylko jednocyfrowe ułamki (niektóre dziesiąte ułamka) lub żadna kropka/przecinek & cyfra w ogóle. Zauważ, że w przeciwieństwie: (a) ISO 8601 pozwala na dowolną liczbę cyfr ułamkowych, a (b) obiekty java.time mają nanosekundową rozdzielczość dla maksymalnie dziewięciu cyfr ułamkowej sekundy.

java.time

Ramy java.time jest wbudowana w Java 8 i późniejszych. Klasy te zastępują stare, kłopotliwe klasy czasu i daty, takie jak java.util.Date, .Calendar, java.text.SimpleDateFormat.

Teraz w maintenance mode, projekt Joda-Time zaleca również migrację do java.time. Aby uzyskać więcej informacji, zobacz

. I wyszukaj Stack Overflow dla wielu przykładów i objaśnień.

Znaczna część funkcjonalności java.time powraca walcowy Java 6 & 7 w ThreeTen-Backport i ponadto dostosowany do Android w ThreeTenABP.

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem wskazującym na możliwe przyszłe dodatki do java.time.

Przetwarzanie

Zdefiniuj wzorzec formatowania, aby pasowały RFC 4517. Study klasę DateTimeFormatter za wzorzec kodowania. To powinno działać: uuuuMMddHHmmss[,S][.S]X. Nawiasy kwadratowe oznaczają opcjonalnie. Możemy pomieścić kropkę lub przecinek. Zwróć uwagę na liczbę pojedynczą ułamka sekundy. Model X na końcu umożliwia albo Z albo offset-from-UTC, taki jak -08 lub -0830 lub -08: 30 lub -083015 lub -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(); 

Zrzut na konsolę.

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

wejściowe: 20090813145607.0Z | odt: 2009-08-13T14: 56: 07Z | natychmiastowy: 2009-08-13T14: 56: 07Z

Oczywiście należy również być kodowanie czek na java.time.format.DateTimeParseException w przypadku niespodziewanego wejścia.

1

Jest to tylko kawałek kodu, który pracował dla mnie:

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