Co to jest format daty? 2011-08-12T20: 17: 46,384Z

381

Mam następujące daty: 2011-08-12T20:17:46.384Z. Jaki to format? Próbuję parsować go za pomocą Java 1.4 przez DateFormat.getDateInstance().parse(dateStr)i otrzymuję

java.text.ParseException: Nieodłączna data: „2011-08-12T20: 17: 46.384Z”

Myślę, że powinienem używać SimpleDateFormat do analizowania, ale najpierw muszę znać ciąg formatu. Do tej pory yyyy-MM-ddmam tylko to , ponieważ nie wiem, co Toznacza ten ciąg - coś związanego ze strefą czasową? Ten ciąg daty pochodzi z lcmis:downloadedOntagu pokazanego na typ nośnika Historia pobierania plików CMIS .

Sarah Vessels
źródło
42
To jest ISO 8601
Tomasz Nurkiewicz,
3
@TomaszNurkiewicz, to nie jest. ISO8601 nie ma na końcu litery Z.
t1gor,
4
ISO8601 doe pozwala Z na końcu. Zobacz powyższy link, poszukaj UTC.
Jonathan Rosenne
2
@ t1gor Na Zkońcu jest skrót Zului oznacza UTC . Ten format z pewnością należy do kolekcji standardowych formatów tekstowych daty i godziny ISO 8601 . Nawiasem mówiąc, te standardowe formaty są domyślnie używane w klasach java.time .
Basil Bourque,
3
Do Twojej wiadomości, kłopotliwe stare klasy daty i czasu, takie jak java.util.Date, java.util.Calendari java.text.SimpleDateFormatsą już starsze , zastąpione przez klasy java.time wbudowane w Javę 8 i Javę 9. Zobacz samouczek Oracle .
Basil Bourque,

Odpowiedzi:

511

T jest po prostu literałem oddzielającym datę od godziny, a Z oznacza „przesunięcie godziny zero” znane również jako „czas Zulu” (UTC). Jeśli ciągi zawsze mają „Z”, możesz użyć:

SimpleDateFormat format = new SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale.US);
format.setTimeZone(TimeZone.getTimeZone("UTC"));

Lub używając Joda Time , możesz użyć ISODateTimeFormat.dateTime().

Jon Skeet
źródło
7
Dlaczego potrzebujemy pojedynczych cytatów Ti Z?
Maroun
7
@MarounMaroun: Zasadniczo chcemy tych dosłownych znaków. Może nie być to konieczne T(nie pamiętam, jak SimpleDateFormat obsługuje nieznane specyfikatory), ale Zchcemy, aby był to znak „Z”, a nie „wartość przesunięcia UTC” (np. „00”).
Jon Skeet
2
@nyedidikeke: Na stronie Wikipedii, do której linkujesz, pokazuje „strefę czasową Zulu” dla UTC. Nie jestem pewien, co według ciebie poprawiasz.
Jon Skeet,
9
@JonSkeet: może wygenerować niepotrzebną debatę; nie kwestionując twojej odpowiedzi, ale zamierzając zwrócić uwagę na literę Z, która otrzymała literę z „zerowego przesunięcia UTC”. Litera Z jest określana jako „Zulu” w alfabecie fonetycznym NATO . Z kolei podejście wojskowe odnoszące się do zerowego przesunięcia UTC jest zakotwiczone na literze Z, którą określają jako Zulu, uzyskując jej zakodowaną nazwę: strefa czasowa Zulu. Należy zauważyć, że Z nie straciło swojego znaczenia i nadal jest wyznacznikiem strefy dla zerowego przesunięcia UTC, ponieważ strefa czasowa Zulu (od Z) jest po prostu odziedziczonym kodowanym językiem, do którego można się odwoływać.
nyedidikeke
2
@nyedidikeke: Nadal nie zgadzam się, czy ktokolwiek kiedykolwiek będzie dbał o to rozróżnienie w odniesieniu do mojej odpowiedzi, ale zaktualizowałem ją. Nie zamierzam jednak wchodzić w szczegóły, ponieważ historia jest zasadniczo nieistotna dla odpowiedzi.
Jon Skeet,
86

tl; dr

Łańcuch wejściowy wykorzystuje standardowy format ISO 8601 .

Instant.parse ( "2011-08-12T20:17:46.384Z" ) 

ISO 8601

Ten format jest określony przez rozsądną praktyczną normę ISO 8601 .

TOddziela część datę z części pomiaru czasu dnia. ZW końcu oznacza UTC (to jest, przesunięciem-z UTC godzinach zero minutowa sekund). ZJest wymawiane „Zulu” .

java.time

Stare klasy daty i czasu w pakiecie z najwcześniejszymi wersjami Javy okazały się źle zaprojektowane, zagmatwane i kłopotliwe. Unikaj ich.

Zamiast tego użyj środowiska java.time wbudowanego w Javę 8 i nowsze wersje . Klasy java.time zastępują zarówno stare klasy daty i godziny, jak i bardzo udaną bibliotekę Joda-Time.

Klasy java.time domyślnie używają ISO 8601 podczas analizowania / generowania tekstowych reprezentacji wartości daty i godziny.

InstantKlasa reprezentuje moment na osi czasu w UTC z rozdzielczością nanosekund . Ta klasa może bezpośrednio analizować ciąg wejściowy bez zawracania sobie głowy definiowaniem wzorca formatowania.

Instant instant = Instant.parse ( "2011-08-12T20:17:46.384Z" ) ;

Tabela typów daty i godziny w Javie, zarówno nowoczesnych, jak i starszych


O java.time

Środowisko java.time jest wbudowane w Javę 8 i nowsze wersje . Klasy te kłopotliwe zastąpić stary starszych klas Date-Time, takich jak java.util.Date, Calendar, i SimpleDateFormat.

Projekt Joda-Time , teraz w trybie konserwacji , zaleca migrację do klas java.time .

Aby dowiedzieć się więcej, zobacz samouczek Oracle . I przeszukaj stos przepełnienia dla wielu przykładów i wyjaśnień. Specyfikacja to JSR 310 .

Gdzie można uzyskać klasy java.time?

Tabela, z której biblioteki java.time należy korzystać, w której wersji Java lub Android

Projekt ThreeTen-Extra rozszerza java.time o dodatkowe klasy. Ten projekt jest poligonem doświadczalnym dla ewentualnych przyszłych dodatków do java.time. Można znaleźć kilka przydatnych klas tutaj takie jak Interval, YearWeek, YearQuarter, i więcej .

Basil Bourque
źródło
3
@star „Zulu” wywodzi się z tradycji wojskowej i lotniczej, w której 25 liter alfabetu AZ (bez „J”), każda litera o wymownej nazwie, reprezentuje ich wersję stref czasowych . Strefa „Zulu” jest przesunięta o zero godzin od UTC. Zobacz to i to .
Basil Bourque,
27

Nie jestem pewien co do analizy Java, ale to ISO8601: http://en.wikipedia.org/wiki/ISO_8601

smparkes
źródło
Czy to także „2016-01-27T17: 44: 55UTC”, ISO8601?
user1997292
Nie wierzę w to. Jest blisko, ale UTC jako przyrostek jest niedozwolony. Musi to być Z lub przesunięcie strefy czasowej, np. +0100. Z i UTC mają jednak to samo znaczenie, więc zmiana UTC na Z dałaby prawidłową ISO 8601.
smparkes 28.01.16
9

Istnieją inne sposoby jego przeanalizowania niż pierwsza odpowiedź. Aby to parsować:

(1) Jeśli chcesz pobrać informacje o dacie i godzinie, możesz parsować je do ZonedDatetime(od Java 8 ) lub Date(starego) obiektu:

// ZonedDateTime's default format requires a zone ID(like [Australia/Sydney]) in the end.
// Here, we provide a format which can parse the string correctly.
DateTimeFormatter dtf = DateTimeFormatter.ISO_DATE_TIME;
ZonedDateTime zdt = ZonedDateTime.parse("2011-08-12T20:17:46.384Z", dtf);

lub

// 'T' is a literal.
// 'X' is ISO Zone Offset[like +01, -08]; For UTC, it is interpreted as 'Z'(Zero) literal.
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSX";

// since no built-in format, we provides pattern directly.
DateFormat df = new SimpleDateFormat(pattern);

Date myDate = df.parse("2011-08-12T20:17:46.384Z");

(2) Jeśli nie obchodzi Cię data i godzina i po prostu chcesz traktować informacje jako chwilę w nanosekundach, możesz użyć Instant:

// The ISO format without zone ID is Instant's default.
// There is no need to pass any format.
Instant ins = Instant.parse("2011-08-12T20:17:46.384Z");
VeryLazyBoy
źródło
1

Jeśli szukacie rozwiązania dla Androida, możecie użyć następującego kodu, aby uzyskać epokę sekund od ciągu znacznika czasu.

public static long timestampToEpochSeconds(String srcTimestamp) {
    long epoch = 0;

    try {
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            Instant instant = Instant.parse(srcTimestamp);
            epoch = instant.getEpochSecond();
        } else {
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd'T'hh:mm:ss.SSSSSS'Z'", Locale.getDefault());
            sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
            Date date = sdf.parse(srcTimestamp);
            if (date != null) {
                epoch = date.getTime() / 1000;
            }
        }
    } catch (Exception e) {
        e.printStackTrace();
    }

    return epoch;
}

Przykładowe dane wejściowe: 2019-10-15T05: 51: 31.537979Z

Przykładowe dane wyjściowe: 1571128673

Rahul Raveendran
źródło
0

Możesz użyć następującego przykładu.

    String date = "2011-08-12T20:17:46.384Z";

    String inputPattern = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";

    String outputPattern = "yyyy-MM-dd HH:mm:ss";

    LocalDateTime inputDate = null;
    String outputDate = null;


    DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern(inputPattern, Locale.ENGLISH);
    DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern(outputPattern, Locale.ENGLISH);

    inputDate = LocalDateTime.parse(date, inputFormatter);
    outputDate = outputFormatter.format(inputDate);

    System.out.println("inputDate: " + inputDate);
    System.out.println("outputDate: " + outputDate);
Salih Kesepara
źródło
Nie powinieneś stawiać apostrofów wokół Z. To oznacza oczekiwać, ale zignorować ten list. Ale tego listu nie należy ignorować. Ta litera dostarcza cennych informacji, ponieważ ciąg był przeznaczony dla UTC, przesunięcie zerowe. Twój format odrzuca ten ważny fakt. Co więcej, nie trzeba nawet zawracać sobie głowy definiowaniem tego wzorca formatowania. Wbudowany jest formatyzator dla tego wzoru.
Basil Bourque
-1

Ta technika tłumaczy java.util.Date na format UTC (lub dowolny inny) iz powrotem.

Zdefiniuj klasę tak:

import java.util.Date;

import org.joda.time.DateTime;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class UtcUtility {

public static DateTimeFormatter UTC = DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").withZoneUTC();


public static Date parse(DateTimeFormatter dateTimeFormatter, String date) {
    return dateTimeFormatter.parseDateTime(date).toDate();
}

public static String format(DateTimeFormatter dateTimeFormatter, Date date) {
    return format(dateTimeFormatter, date.getTime());
}

private static String format(DateTimeFormatter dateTimeFormatter, long timeInMillis) {
    DateTime dateTime = new DateTime(timeInMillis);
    String formattedString = dateTimeFormatter.print(dateTime);
    return formattedString;
}

}

Następnie użyj go w następujący sposób:

Date date = format(UTC, "2020-04-19T00:30:07.000Z")

lub

String date = parse(UTC, new Date())

Możesz także zdefiniować inne formaty dat, jeśli potrzebujesz (nie tylko UTC)

Gapmeister66
źródło
Zarówno java.util.Dateprojekt Joda-Time został wyparty wiele lat temu przez nowoczesne klasy java.time zdefiniowane w JSR 310. Ta rada jest od dawna nieaktualna.
Basil Bourque
java.time został wprowadzony w Javie 8. To pytanie dotyczy konkretnie Java 1.4 i dlatego celowo uniknąłem używania nowszych klas. To rozwiązanie obsługuje starsze bazy kodu. Podejrzewam, że autor mógł przenieść swoją bazę kodu na Javę 8, ale nie zawsze jest to proste, wydajne lub konieczne.
Gapmeister66
-1

@ John-Skeet dał mi wskazówkę, że mogę rozwiązać mój własny problem. Jako młodszy programista ten niewielki problem jest łatwy do przeoczenia i trudny do zdiagnozowania. Więc dzielę się tym w nadziei, że to komuś pomoże.

Mój problem polegał na tym, że chciałem przeanalizować następujący ciąg zawierający znacznik czasu z JSON, na który nie mam wpływu, i umieścić go w bardziej przydatnych zmiennych. Ale ciągle pojawiały się błędy.

Biorąc pod uwagę następujące (należy zwrócić uwagę na parametr string wewnątrzPattern ();

String str = "20190927T182730.000Z"

LocalDateTime fin;
fin = LocalDateTime.parse( str, DateTimeFormatter.ofPattern("yyyyMMdd'T'HHmmss.SSSZ") );

Błąd:

Exception in thread "main" java.time.format.DateTimeParseException: Text 
'20190927T182730.000Z' could not be parsed at index 19

Problem? Z na końcu Wzorca musi być zawinięte w „Z” tak jak „T”. Zmień "yyyyMMdd'T'HHmmss.SSSZ"na "yyyyMMdd'T'HHmmss.SSS'Z'"i to działa.

Całkowite usunięcie Z ze wzoru również doprowadziło do błędów.

Szczerze mówiąc, spodziewałbym się, że klasa Java to przewidziała.

spencemw
źródło
1
To pytanie zostało już zadane i udzielone tutaj i tutaj . A twoje rozwiązanie jest złe. Chociaż Tjest dosłowny i wymaga cytowania, Zjest przesunięciem (zerem) i musi zostać przeanalizowany jako taki, w przeciwnym razie otrzymasz błędne wyniki. Nie wiem, co masz na myśli, że nie zostało to przewidziane, wierzę, że tak.
Ole VV
1
Nie, nie, nie, nie ignoruj Z. Odrzucasz cenne informacje. Przetwarzanie wartości daty i godziny przy ignorowaniu strefy czasowej lub przesunięciu względem UTC jest jak przetwarzanie kwoty pieniędzy przy ignorowaniu waluty!
Basil Bourque,
1
TJedynie oddziela część datę z części czasu w dzień, i dodaje żadnego znaczenia. Z Zdrugiej strony zdecydowanie dodaje znaczenia.
Basil Bourque
Ole, dzięki za linki. Z pewnością je przeczytam. I zgadzam się, że z pewnością mogę się mylić jako młody chłopak. Chodzi mi tylko o to, że zawarcie Z w pojedynczych cudzysłowach jak znak char we wzorze rozwiązało błąd. Moja krytyka polega na tym, że ktokolwiek zaprojektował „klasę” części klasy, mógł zakodować obecność lub nieobecność „Z” (lub innej strefy czasowej?) I „T” jest zawinięte w „”, czy nie. Ponieważ nie zrobili tego wyjątkowy. Format, z którym mam do czynienia, pochodzi z JSON z komercyjnego API parsowanego na ciąg znaków. Ale muszę to wszystko przeanalizować w kalendarzu daty, itp., Aby były bardziej przydatne.
spencemw