Dzięki różnorodności kultur na Ziemi mamy różne formaty dat. W przypadku dat numerycznych mamy miesiąc-dzień-rok, dzień-miesiąc-rok i rok-miesiąc-dzień. Posiadamy również krótkie i długie formaty. Daty można mieszać z czasem, co jest inną historią. Ta rzeczywistość podąża za nami w pracy. Dlatego format daty SQL nie jest czymś, co możemy łatwo przyjąć.
Na Filipinach używamy 2 formatów:miesiąc-dzień-rok i dzień-miesiąc-rok. Miesiąc-dzień-rok to ogólny format dat liczbowych. Ale w przypadku dłuższych formatów dat zamiennie używamy dzień-miesiąc-rok i miesiąc-dzień-rok.
W pracy nigdy nie spotkałem się z ustawieniem formatu daty SQL Server innym niż miesiąc-dzień-rok. Różni się jednak w raportach i plikach wymiany danych i projekcie Extract-Transform-Load (ETL). Nie mówiąc już o użytkownikach, którzy zmieniają to w swoich stacjach pod kątem osobistych preferencji! We wszystkich tych scenariuszach nieodpowiednie radzenie sobie z nimi jest receptą na zerwanie.
Czy Twoje aplikacje dotyczą różnych kultur? To kolejny poziom złożoności i problem, gdy mamy do czynienia z różnymi formatami daty SQL. W tym artykule przyjrzymy się standardowi, aby poradzić sobie z wszystkimi tymi odmianami i przykładami. Czytaj dalej do końca! Ale zanim przejdziemy dalej, zróbmy krótką wycieczkę po tym, jak SQL Server przechowuje daty.
Jak SQL Server przechowuje daty
Zgadnij. Czy SQL Server przechowuje 29.03.2021 21:35 tak jak w bazie danych? A może 2021-03-29? Czy są przechowywane jako sformatowane ciągi? Bazując na tej dokumentacji firmy Microsoft, tak nie jest.
Weźmy na przykład typ danych DATE. Jest przechowywany jako 3-bajtowa liczba całkowita.
Skąd wiemy?
Cóż, Microsoft twierdzi, że tak jest, ale nie podaje więcej informacji. To nie znaczy, że nie możemy tego wiedzieć na pewno. Po pierwsze, minimalna wartość typu danych DATE to 01/01/0001 lub 1 stycznia 1 CE lub Common Era. Aby przekonwertować to na liczbę całkowitą, najpierw konwertujemy tę datę na VARBINARY, tak jak poniżej:
SELECT CAST(CAST('01/01/0001' AS DATE) AS VARBINARY(3))
Wynik to 0x000000 w formacie szesnastkowym. Z tej wartości widzimy, że wartość całkowita z 1 stycznia 1 CE wynosi 0. Jest to logiczne, ponieważ jest to minimalna wartość DATY.
Teraz posuwamy się do przodu o 1 dzień.
SELECT CAST(CAST('01/02/0001' AS DATE) AS VARBINARY(3)) -- January 2, 1 CE
Wynik to 0x010000 . To trochę trudne, ale ten post dał nam pomysł. Nie możemy tego traktować tak, jak to widzimy. Bajty są odwrócone, a rzeczywista wartość szesnastkowa to 0x000001 . Jeśli znasz się trochę na liczbach szesnastkowych, wiesz, że to jest równe 1 – to 1 dzień od punktu startowego, czyli 1 stycznia 1 roku n.e.
Teraz wypróbujmy ostatnią datę:29.03.2021.
SELECT CAST(CAST('03/29/2021' AS DATE) AS VARBINARY(3))
Wynik to 0x55420B . Kiedy go odwrócimy, staje się 0x0B4255 . Tym razem nie możemy poznać wartości, patrząc na nią. Tak więc mnożymy ją przez 1 jako liczbę całkowitą.
SELECT 0x0B4255 * CAST(1 AS INT)
Wynik to 737.877 . Jest to liczba dni od 1 stycznia 1 roku n.e. Zweryfikujmy to za pomocą DATEDIFF.
SELECT DATEDIFF(DAY,CAST('01/01/0001' AS DATE),CAST('03/29/2021' AS DATE))
Wynik jest taki sam:737.877 dni. Bardzo fajnie!
Koniec:sformatowana data służy wyłącznie do celów prezentacyjnych
W ten sposób SQL Server przechowuje typy danych DATE. Inaczej jest w przypadku DATETIME, SMALLDATETIME i DATETIME2, ale nadal jest przechowywany jako liczby całkowite. SQL Server oblicza czas trwania od punktu początkowego i wyświetla datę, którą wszyscy rozumiemy.
Niezależnie od tego, czy patrzysz na to w SQL Server Management Studio, dbForge Studio dla SQL Server, czy w swojej aplikacji, 29.03.2021 to tylko prezentacja. Jeśli zmienisz region lub język, przechowywana wartość 0x55420B pozostanie bez zmian.
Teraz wiemy, że daty nie są przechowywane jako ciągi. Możemy zapomnieć o przechowywaniu dat w określonym formacie . I tak to nie działa. Zamiast tego przyjrzyjmy się różnym sposobom w SQL na formatowanie dat, których potrzebują Twoje aplikacje.
4 łatwe sposoby formatowania dat
Przeanalizujmy następujące funkcje daty SQL:
- Funkcja KONWERSJA
- USTAW JĘZYK
- USTAW FORMAT DATY
- Funkcja FORMATU
Możesz także użyć programu do formatowania zapytań SQL.
1. Funkcja KONWERSJI
CONVERT to jedna z funkcji konwersji danych, która może również służyć do formatowania daty. Rysunek 1 przedstawia przykład.
Pierwsze dwa argumenty CONVERT to docelowy typ danych i wartość daty. Trzecie jest opcjonalne, ale dotyczy również dat. Wartości liczbowe to style formatu daty SQL, które mają być używane podczas konwersji z daty na ciąg.
Na rysunku 1 Japonia używa formatu rok-miesiąc-dzień z ukośnikiem jako separatorem. Niemcy stosują dzień-miesiąc-rok z kropkami jako separatorami. Wielka Brytania i Francja używają tej samej sekwencji co Niemcy, ale z ukośnikiem jako separatorem. Tylko Stany Zjednoczone stosują miesiąc-dzień-rok z myślnikiem jako separatorem.
W SQL możesz również przekonwertować wyrażenie DATETIME na DATE.
Aby uzyskać pełną listę stylów formatu daty CONVERT w SQL, sprawdź ten dokument firmy Microsoft.
2. USTAW JĘZYK
To ustawienie określa język zastosowany do sesji. Ma to wpływ na formaty dat i komunikaty systemowe. Kiedy ustawiasz język, domyślnie stosujesz również ustawienia SET DATEFORMAT (omówimy to później).
Na razie sprawdźmy przykłady na rysunku 2. Zmieniam ustawienia języka na litewski, a następnie z powrotem na angielski.
Spójrz na rysunek 2. Litewski format daty to rok-miesiąc-dzień. Ilekroć próbuję różnych dat, długa data zawsze zawiera „m.” przed miesiącem i „d.” po dniu. Pierwsza litera miesiąca i nazwa dnia tygodnia również nie są pisane wielką literą. W przypadku innych ustawień językowych jest inaczej, ale rozumiesz.
Aby uzyskać więcej informacji na temat USTAW JĘZYK, zapoznaj się z tym dokumentem firmy Microsoft.
3. USTAW FORMAT DATY
To ustawienie umieszcza kolejność miesiąca, dnia i roku w interpretacji ciągów znaków daty. Zastąpi niejawne ustawienia formatu daty wykonane przez SET LANGUAGE. Oto przykład na rysunku 3.
Na rysunku 3 kod używa formatu DMY lub dzień-miesiąc-rok. Zgodnie z tymi ustawieniami każda wartość daty ustawiona na zmienną daty powinna być zgodna z tym wzorcem. 30.03.2021 pasuje do tego formatu, ale 31.03.2021 powoduje błąd, ponieważ 31 nie jest prawidłowym miesiącem.
W związku z tym zmiany w formacie daty mogą spowodować uszkodzenie aplikacji, jeśli logika działa na podstawie innego formatu.
Aby uzyskać więcej informacji na temat SET DATEFORMAT, zapoznaj się z tym dokumentem firmy Microsoft.
4. Funkcja FORMATU
Ze wszystkich dostępnych opcji formatowania ta jest najbardziej elastyczna. Podobnie jest z formatowaniem daty w .Net, ponieważ FORMAT opiera się na obecności .Net Framework na serwerze, na którym zainstalowany jest SQL Server. To jednak wada tej opcji.
Podobnie jak w C#, FORMAT przyjmuje wartość daty i ciąg formatu. Zróbmy kilka przykładów na rysunku 4.
Podobnie jak w .Net, w SQL Server możesz formatować daty za pomocą różnych separatorów. Ponadto możesz umieścić miesiąc, dzień i rok w dowolnym miejscu. Następnie możesz uzyskać informacje kulturowe i użyć ich formatu daty.
Aby uzyskać więcej informacji i przykładów dotyczących FORMATU, zapoznaj się z tym dokumentem firmy Microsoft.
Teraz zidentyfikowaliśmy 4 sposoby formatowania dat i różnorodność formatów dat. Czy istnieje standardowy format, który zawsze działa podczas konwersji ciągów na daty?
ISO 8601 — najbardziej przenośny, wolny od błędów format daty SQL, którego można użyć do konwersji
ISO 8601 istnieje od 1988 roku. Jest to międzynarodowy standard wymiany danych dotyczących dat i godzin .
Jest również dostępny w funkcji CONVERT jako jeden ze stylów formatu daty:style 126 i 127 są zgodne z ISO 8601.
Co sprawia, że jest przenośny i wolny od błędów?
Problem z formatami innymi niż ISO 8601
Zademonstrujmy problem związany z niezgodnością z ISO 8601 na przykładzie:
DECLARE @d VARCHAR(10) = '03/09/2021';
SET LANGUAGE Italian;
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET LANGUAGE English
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET DATEFORMAT DMY
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
SET DATEFORMAT MDY
SELECT FORMAT(CONVERT(DATETIME, @d),'D')
W zależności od lokalizacji daty możesz zinterpretować @d jako 9 marca 2021 lub 3 września 2021. Nie możesz być pewien, który jest który. W tym właśnie tkwi problem.
Sprawdź wynik na Rysunku 5 poniżej:
Nawet SQL Server nie wie tego na pewno!
Co gorsza, tego rodzaju scenariusz może zepsuć twoją aplikację, tak jak to miało miejsce na rysunku 3 wcześniej. Ta sytuacja jest problematyczna w przypadku aplikacji obsługujących wielokulturowych użytkowników.
Czy ISO 8601 może w tym pomóc?
Korzystanie z ISO 8601 do rozwiązywania problemów z formatowaniem
Zwróć uwagę, kiedy format ISO 8601 rrrrMMdd jest używany zamiast MM/dd/rrrr i sprawdź wynik na rysunku 6:
Zawsze będzie 9 marca, bez względu na używany język i format daty. Jest to idealne rozwiązanie do wymiany danych i integracji systemów. Jeśli twój użytkownik ma inny format daty w stacji, to również nie ma znaczenia.
Jeśli chcesz przekształcić daty w ciągi i odwrotnie, użyj ISO 8601.
ISO 8601 w SQL Server występuje w 2 wersjach:
- RRRRMMDD dotyczy tylko dat.
- RRRR-MM-DDTHH:MM:SS dla połączenia daty i czasu, gdzie T jest separatorem między datą a godziną.
Inne sposoby obsługi formatów dat z aplikacji do SQL Server
1. Użyj kontroli daty w aplikacji
Gdy poprosisz użytkownika o wprowadzenie dat w formularzu, nie pozwól mu używać dowolnego tekstu. Użyj kontrolek daty, które umożliwiają wybór tylko z prawidłowych wartości.
2. Konwertuj na inny format tylko w razie potrzeby
Nie zmieniaj dat na ciągi i odwrotnie. Użyj natywnych typów danych Date lub DateTime aplikacji wywołującej. Jeśli z jakiegoś powodu musisz je przekształcić, użyj ISO 8601.
3. Ustaw datę/godzinę, strefę czasową i kulturę podczas uruchamiania aplikacji, jeśli ma to zastosowanie
Jeśli Twoja aplikacja korzysta ze stałego formatu daty, a Twoi użytkownicy uwielbiają dostosowywać formaty dat, możesz naprawić oba te formaty podczas uruchamiania aplikacji. Określ wyraźnie, czego potrzebuje Twoja aplikacja. Będzie znacznie lepiej, jeśli administrator sieci będzie mógł zablokować te ustawienia.
Na wynos
Czy zatem obsługa różnych formatów daty SQL jest przytłaczająca? Nie mogę cię winić, jeśli nadal tak to uważasz, ale dowiedzieliśmy się, że nie jest to niemożliwe.
Oto, co omówiliśmy:
- Daty SQL są przechowywane jako liczby całkowite . To, co widzimy naszymi oczami, jest już sformatowane w oparciu o ustawienia SQL Server. Bez względu na to, ile razy zmienimy język i format daty, przechowywana wartość pozostanie taka sama. Nie ma sensu myśleć o przechowywaniu dat w określonym formacie.
- Istnieją 4 sposoby formatowania dat:KONWERSJA , USTAW JĘZYK , USTAW FORMAT DATY i FORMAT .
- Jeśli chcesz przekształcić daty w ciągi i odwrotnie, użyj formatu ISO 8601 .
- Istnieją 3 inne sposoby radzenia sobie z formatami dat:
- korzystanie z kontroli rozpoznających datę w Twojej aplikacji;
- przekształcanie dat w ciągi znaków tylko w razie potrzeby;
- ustawianie wymaganej strefy czasowej, kultury, daty/godziny serwera podczas uruchamiania, jeśli dotyczy .
Czy uważasz, że przyda się to Tobie i innym? Następnie udostępnij ten artykuł na swoich ulubionych platformach społecznościowych.