Heim > Java > javaLernprogramm > Hauptteil

Lasst uns Dates richtig machen

王林
Freigeben: 2024-08-05 20:17:30
Original
1066 Leute haben es durchsucht

Lets do dates properly

Als Anfänger sind Dates eines der interessantesten Themen, die Sie lernen werden. Auch wenn es etwas langweilig klingt, ist es eines der wichtigsten Dinge, die Sie vielleicht wissen; aus Ihrer Datenbank, API, GUI und mehr zu lernen, wie man richtig mit Datumsangaben umgeht, ist ein Schlüsselfaktor beim Schreiben guter Anwendungen.

Bevor wir beginnen

Ein wichtiges Detail, an das Sie sich erinnern müssen, ist, dass Java schnell für das Web entwickelt wurde, sodass es viele skurrile und etwas dumme Möglichkeiten gibt, Dinge zu tun. Das Ziel dieses Leitfadens besteht darin, Ihnen beizubringen, wie Sie mit den neuesten Java-APIs effizienten und guten Code schreiben. Mein Ziel ist es, Ihnen beizubringen, wie Sie nichts schwer programmieren und stattdessen standardisierte ISO-Codes für eine skalierbare Anwendung verwenden.

So arbeiten Sie mit Daten

Die Datums-API

Ab Java 8 SE mit der Veröffentlichung der Datumsklasse definiert als:

Die Klasse „Datum“ stellt einen bestimmten Zeitpunkt mit Millisekundengenauigkeit dar.

Außerdem wurde im weiteren Verlauf die Klasse „Abstrakter Kalender“ (mit deutlichem Upgrade mit JDK 1.1) hinzugefügt, die wie folgt definiert ist:

Die Calendar-Klasse ist eine abstrakte Klasse, die Methoden zum Konvertieren zwischen einem bestimmten Zeitpunkt und einer Reihe von Kalenderfeldern wie YEAR, MONTH, DAY_OF_MONTH, HOUR usw. sowie zum Bearbeiten der Kalenderfelder bereitstellt, z das Datum der nächsten Woche abrufen. Ein Zeitpunkt kann durch einen Millisekundenwert dargestellt werden, der einen Offset von der Epoche, 1. Januar 1970 00:00:00.000 GMT (Gregorianisch), darstellt.

Wie aus den Oracle-Dokumenten hervorgeht, war der Grund der Mangel an Internationalisierungsfähigkeiten.

Es ist gut zu beachten, dass die oben verlinkte Dokumentation detaillierter auf den Zeitpunkt eingeht, falls Sie daran interessiert sind.

Die LocalDate-API

Außerdem kam mit Java 8 SE die LocalDate-Klasse, auf die verwiesen wird:

Ein Datum ohne Zeitzone im ISO-8601-Kalendersystem, z. B. 2007-12-03.
LocalDate ist ein unveränderliches Datum-Uhrzeit-Objekt, das ein Datum darstellt, das oft als Jahr-Monat-Tag angesehen wird. Auf andere Datumsfelder wie Tag des Jahres, Wochentag und Woche des Jahres kann ebenfalls zugegriffen werden. Beispielsweise kann der Wert „2. Oktober 2007“ in einem LocalDate.

gespeichert werden

Eine wichtige Spezifikation, die Sie beachten sollten, ist:

Diese Klasse speichert oder repräsentiert keine Zeit oder Zeitzone. Stattdessen handelt es sich um eine Datumsbeschreibung, wie sie bei Geburtstagen verwendet wird. Es kann keinen Zeitpunkt auf der Zeitachse ohne zusätzliche Informationen wie einen Versatz oder eine Zeitzone darstellen.

Unterschied und welches zu verwenden ist

Probleme mit den Datums-/Uhrzeit-APIs

Wenn Sie die LocalDate-Klasse weiter lesen, werden Sie zu „Diese Klasse ist unveränderlich und threadsicher“ gelangen. Das bringt uns zu unserem ersten Problem.

  • Sowohl das Datum als auch der Kalender waren nicht threadsicher. Wenn Sie etwas verwirrt sind, was das bedeutet: Threads sind eine Möglichkeit, Parallelität mit einer Computeranwendung zu implementieren. Dadurch können mehrere Aufgaben gleichzeitig und nicht nacheinander ausgeführt werden. (Wenn Sie über einen Programmierhintergrund verfügen, können Sie dies als asynchron betrachten.) .
  • Ein weiteres Problem mit der Datums-/Kalender-API war ihr schlechtes Design. Später wurde es so umgestaltet, dass es ISO-zentriert ist (falls Sie nicht wissen, was diese ganze ISO-Sache ist; kurz ISO steht für „International Organization for Standardization“). Die zusätzlichen Vorteile davon werden wir später sehen.
  • Abschließend komme ich noch einmal auf die mangelnde Internationalisierung zurück: Entwickler mussten ihre Logik für den Umgang mit unterschiedlichen Zeitzonen schreiben, was zu vielen Fehlern wie fehlenden Übereinstimmungen führen kann.

Der tatsächliche Unterschied

Der größte Unterschied besteht darin, dass „Date“ trotz des Namens sowohl Uhrzeit als auch Datum speichert (wie in den Dokumenten erwähnt, mit Millisekunden-Versatz seit der Epoche – wir werden später über die Epoche sprechen). Mit der neueren API erhalten wir Zugriff auf eine einfachere Formatierung/Analyse/Manipulation von Datumsangaben.

Was ist, wenn ich auch Zeit speichern möchte?

Nun, Java deckt Sie auch hier mit seiner LocalDateTime-Klasse ab

Ein Datum und eine Uhrzeit ohne Zeitzone im ISO-8601-Kalendersystem, z. B. 2007-12-03T10:15:30.
LocalDateTime ist ein unveränderliches Datum-Uhrzeit-Objekt, das ein Datum und eine Uhrzeit darstellt, oft betrachtet als Jahr-Monat-Tag-Stunde-Minute-Sekunde. Auf andere Datums- und Zeitfelder wie Tag des Jahres, Wochentag und Woche des Jahres kann ebenfalls zugegriffen werden. Die Zeit wird mit einer Genauigkeit im Nanosekundenbereich dargestellt. Beispielsweise kann der Wert „2. Oktober 2007 um 13:45.30.123456789“ in einem LocalDateTime.

gespeichert werden

Wenn Sie nur Zeit speichern möchten, können Sie die LocalTime-Klasse verwenden

Kurze kleine Zusammenfassung und Anwendungsfälle

Name Should Use Use Case Example
LocalDate Interprating Dates 2021-02-28
LocalTime Interprating Time 19:32:25.457826
LocalDateTime Interprating Time/Date 2021-02-28T19:32:25.457826.
Date prefer not Represents Time Tue Jul 12 18:35:37 IST 2016

Lokales Datum

Da wir nun den Hintergrund und die Möglichkeiten, die wir damit machen können, gut verstehen, wollen wir uns mit den Methoden der LocalDate-Klasse befassen.

ISO 8601

Das ISO-8601-Kalendersystem ist das moderne zivile Kalendersystem, das heute in den meisten Teilen der Welt verwendet wird. Es entspricht dem proleptischen gregorianischen Kalendersystem, bei dem die heutigen Regeln für Schaltjahre für alle Zeiten gelten. Für die meisten heute geschriebenen Anwendungen sind die ISO-8601-Regeln durchaus geeignet. Für jede Anwendung, die historische Daten verwendet und deren Genauigkeit erfordert, ist der ISO-8601-Ansatz jedoch ungeeignet.

Dies ist der Standard, den Java verwendet, um unsere Daten richtig zu formatieren.

Zeitlich

Bevor wir näher darauf eingehen, möchte ich Ihnen das Temporal-Objekt vorstellen, das alle neuen Datums-APIs implementieren (LocalDate, LocalTime, LocalDateTime). Es ist wie folgt definiert:

Dies ist der Basisschnittstellentyp für Datums-, Uhrzeit- und Offset-Objekte, die vollständig genug sind, um mit Plus und Minus manipuliert zu werden. Es wird von den Klassen implementiert, die Informationen als Felder oder Abfragen bereitstellen und bearbeiten können. Die schreibgeschützte Version dieser Schnittstelle finden Sie unter TemporalAccessor.

Ich möchte nicht näher darauf eingehen, ich wollte nur, dass ihr versteht, was das ist, wenn ihr darauf stößt.

Methoden

Das Format dafür ist in der richtigen Reihenfolge: Der Methodenname, die angegebene Rückgabebeschreibung und eine kurze Zusammenfassung dessen, was sie tut/oder ein ausführlicher Einblick. Wenn Sie mitmachen möchten, verwende ich jshell, importieren Sie einfach java.time.LocalDate und kopieren Sie die gleichen Methoden.

LocalDate.now(): > das aktuelle Datum unter Verwendung der Systemuhr und der Standardzeitzone, nicht null

Wie in der Beschreibung erwähnt, wird das aktuelle Datumsformat basierend auf der Zeitzone zurückgegeben. Bei mir ist es beispielsweise der 10.07.2024. Das Format kann sich jedoch je nach Ortszeit ändern, abhängig vom für Ihr Land zugewiesenen ISO 8601-Format (z. B. könnte es 2024.07.10 oder 24/7/10 sein. Dies ist ein Standard, den Ihr Land verwenden würde)

Die LocalDate.now()-Methode kann ein Argument annehmen. Um dies zu nutzen, importieren wir java.time.ZoneId.

Was ist ZoneId?

ZoneId Veröffentlicht mit Java 8SE definiert als:

Eine ZoneId wird verwendet, um die Regeln zu identifizieren, die zum Konvertieren zwischen einem Instant und einem LocalDateTime verwendet werden. Es gibt zwei verschiedene Arten von IDs:

  • Feste Offsets – ein vollständig aufgelöster Offset von UTC/Greenwich, der den gleichen Offset für alle lokalen Datums- und Uhrzeitangaben verwendet
  • Geografische Regionen – ein Gebiet, in dem bestimmte Regeln zum Ermitteln des Offsets von UTC/Greenwich gelten

Einfach ausgedrückt löst dies das Internationalisierungsproblem, das wir mit der alten Date-API hatten. Nach dem Import von java.time.ZoneId können wir uns einige der Methoden ansehen, die es zu bieten hat.

  • ZoneId.getAvailableZoneIds() Zeigt uns alle verfügbaren Zonen an, hier einige zum Beispiel: Europa/Istanbul, Amerika/Eirunepe usw./GMT-4, Amerika/Miquelon (Denken Sie daran, dass jede davon einzigartig ist und wir zwei Arten eindeutiger IDs haben sind oben aufgeführt).
  • ZoneId.systemDefault() Die Methode ist definiert als „Wenn die Standardzeitzone des Systems geändert wird, ändert sich auch das Ergebnis dieser Methode.“ Was selbsterklärend ist.
  • ZoneId.of("") Wir verwenden dies, um eine benutzerdefinierte festgelegte ZoneId aus der Liste .getAvailableZoneIds() zu definieren. Denken Sie daran, dass sowohl UTC als auch Europa/Istanbul, die hier als Beispiel verwendet werden, verwendet werden können.
  • ZoneId.from() Erinnern Sie sich an die Zeitlichkeit, über die wir zuvor gesprochen haben? Hier werden wir es als Argument übergeben. Wenn Sie nicht ganz sicher sind, was dies bewirkt, erhalten wir bei einem ==TemporalAccessor, der einen beliebigen Satz von Datums- und Uhrzeitinformationen darstellt, eine ZoneId. Wenn Sie noch etwas ahnungslos sind, können Sie java.time.ZoneId importieren und ZonedDateTime.now() verwenden, um eine genaue Uhrzeit/ein genaues Datum zu erhalten, das Sie dann in eine ZoneId analysieren können. Grundsätzlich ZoneId.from(ZonedDateTime.now())

Es gibt auch ein Clock-Argument, das Sie weitergeben können, aber ich sehe keinen Nutzen dafür, wenn Sie einfach ZoneID verwenden könnten, aber zögern Sie nicht, das auszuprobieren

Jetzt, wo wir das erfahren haben – schauen wir uns das aktuelle Datum in Paris an!

LocalDate.now(ZoneId.of("Europe/Paris")) // 2024-07-10
Nach dem Login kopieren
LocalDate.of(Jahr, Monat, Tag des Monats): > Ruft eine Instanz von LocalDate aus einem Jahr, einem Monat und einem Tag ab.

Denken Sie daran, dass LocalDate ein Datum darstellt. In diesem Fall können wir dieses Datum auf ein beliebiges Jahr, einen beliebigen Monat und einen beliebigen Tag einstellen!

LocalDate.ofYearDay(year, dayOfYear): >

In vielen Fällen haben Sie möglicherweise nur ein Jahr und einen Tag. Diese Funktion wandelt es in ein Jahr-Monat-Tag-Format um. Hier ist ein Beispiel: LocalDate.ofYearDay(2023, 234) wird der 22.08.2023 sein. Auch Schaltjahre werden berücksichtigt.

LocalDate.parse(text) : > Obtains an instance of LocalDate from a text string using a specific format.

Basically, if we generate a String Date format like 2023-08-22 this will convert it into a LocalDate format

Epoch

There’s one last method I would like to talk about and even though it might not be that useful, it's a good thing to know.
Epoch in simple terms is a date set to the start. Virtually means it's “The start of time”. For example UNIX epoch is set to 1970/1/1 This is when all Unix time is calculated. Now this is not standardized between all computers. Most programming languages will use the UNIX epoch but not between all devices. For example NTP epoch is 1900/1/1. Now you might be asking why. And the simple answer is I don’t know. Unix was developed in 1969 and released in 71 but I guess the developers found 70 easier to work with and now that’s what we use!

LocalDate.ofEpochDay(epochDay) : >

Just going based on the description I gave about the output of this would be X days from 1970/1/1. Given epochDay is 1 => 1970-01-02 and so on.

~
~
~

By now I think you guys are all bored of all this nerdy talk and most likely lost interest completely but we are going to make it way more interesting in just a bit.
LocalDate methods have a ton of subsets to modify dates as we talked about above. Explaining all of these is just a waste of time. The best thing is for you guys to check ’em out and play around a bit, they are all very simple to understand.

Locale

The main idea of this whole article was to teach you internationalization and we are going to start that now.
If you recall above I talked about how LocalDate.now() might show different numbers/punctuations and this is standardized by Locale Class

A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user. For example, displaying a number is a locale-sensitive operation— the number should be formatted according to the customs and conventions of the user's native country, region, or culture.

Again the Locale class uses pre-defined ISO standards that Oracle has included.

As I said - In the early days of the web Java was rushed and we can really see that here.

Locale Constant & Why not to use

If you import java.util.Locale you can see that we have a few constants. Locale.CANADA as an example. If you're wondering what these are and why they were picked, it's quite simple. Due to the reason mentioned above, the Java devs just picked some Locale constants to support and you should not use them. Now if you look closely we have a Locale.French
and a Locale.France and you might be confused, what is this?? I’ll talk about it in a second

Now how do we go about using these Locales? By using Locale.availableLocales() you will see a large subset of available locales that you can use. you might see it in the format of en_US and you might get confused. Following up on the question listed above Java has accounted for different language subsets used in different countries. In this France/French example, We can refer to Canadian French versus French used in France. They are not entirely the same. Now a country like Iran will use Persian no matter the place, so you could just use Locale.of(language) to specify the Locale, But for French you could rather use Locale.of(language, country). Remember if you split what you got from Locale.availableLocales() by the _ you can just format it like that. An example would be Locale.of("en", "US") for en_US

Now let's implement this into our time for our different users around the globe.

System.out.println(
LocalDate.now().format(

DateTimeFormatter

.ofLocalizedDate(FormatStyle.SHORT)

.localizedBy(Locale.GERMAN)));
Nach dem Login kopieren

Now don’t mind the extra code, and even me using Locale.GERMAN cause honestly I was looking for a different output and the easiest way was to use Javas constants. I landed on Locale.GERMAN which outputs 10.07.24 as opposed to what Japan uses (2024/07/10).

Why not use Locale.of()

Now it might sound weird, but first of all i tell you not to use constants and prefer Locale.of(), then I tell you not to use Locale.of() an important factor to consider is Locale.of() was introduced with Java 19 which goes against supporting Java 8 SE to combat that from now on we will use

new Locale.Builder()
            .setLanguage("language")
            .setRegion("country").build();
Nach dem Login kopieren

Now another thing you could use is Locale.setDefault(language, country) which will work as well.

DateTimeFormatter

Now looking at the code above you might recall seeing DateTimeFormatter defined by docs as:

Formatter for printing and parsing date-time objects.

LocalDate.format()

As I mentioned above, one of the key features of Date/Time Local* APIs was formatting. And this is how we are going to format our dates. Looking at the code above - everything should make sense apart from the .ofLocalizedDate() method. The easiest way to show what it does is with an example.

LocalDate anotherSummerDay = LocalDate.of(2016, 8, 23);
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.LONG).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM).format(anotherSummerDay));
System.out.println(DateTimeFormatter.ofLocalizedDate(FormatStyle.SHORT).format(anotherSummerDay));
Nach dem Login kopieren

will output the following in order:

Tuesday, August 23, 2016
August 23, 2016
Aug 23, 2016
8/23/16
Nach dem Login kopieren

Now sometimes you might want to have your own pattern which you can easily do with

System.out.println(

LocalDate.now().format(

DateTimeFormatter

.ofPattern("dd-uuuu-MMM")));
Nach dem Login kopieren

Now I’ll quickly go over what these symbols mean:
dd => It's a representation of the day field, now you could also use d and the difference would be that d would not have a fixed character limit since it represents 1 digit from 0-9 and 2 from 10-31. if you're lost it basically means dd would show 01; however d would show 1. However, going into two digits it's the same
uuuu/yyyy => Is the field for years. And you could also do yy which would show only the last two digits of the year. ex. 24 rather than 2024
MMM => The last field as you might have guessed is for the month - MMM tells Java that we want a String representation rather than a number. If you want a number use MM

So by now, you should’ve guessed that the output would be:

10-2024-Jul
Nach dem Login kopieren

Instants

Now that you have a firm grip on Dates. I want to introduce you to Instants defined as:

An instantaneous point on the timeline.

Basically, this refers to Instants showing a specific moment.
By now you might have assumed that LocalDateTime has a timezone, but it doesn’t as the docs mentioned they are just a representation of date/time. However a ZoneId is in fact a representation of a time zone. Also, note that Instants don’t provide methods for altering our dates and times.

Instants capture the current moment in UTC with the Instant.now() . Now based on this, you realize that Local* really doesn’t have a meaning unless it's applied, that’s the reason why you would actually refrain from using it in a business-level application. So prefer using ZonedDateTime and Insant. As a general rule of thumb use Locale When it's a specific point on a timeline rather than a moment in time. A moment would be like the moment I publish this, or the moment you read this, or the moment the world explodes, however a point in a timeline would be like an appointment there’s no moment for an appointment. If you're going on a vacation it's a specific time on a timeline, not a moment.

Whats ZonedDateTime?

Quite simple. It's just an Instant with a ZoneId and this is why we say Insant has a timezone. No matter what you do it's not going to represent a time but rather be a specific moment.

Aigh’t well that was quite the thing, wasn’t it? phew
have a nice one >#

Das obige ist der detaillierte Inhalt vonLasst uns Dates richtig machen. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Quelle:dev.to
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!