Przechowywanie daty w bazie danych

Przechowywanie daty w bazie danych
RE
  • Rejestracja:około 4 lata
  • Ostatnio:ponad 3 lata
  • Postów:66
0

Potrzebuję porady odnośnie przechowywania dat. Nigdy się na tym nie zastanawiałem, aż do czasu odkrycia, że różne języki/biblioteki różnie podchodzą do tematu. Format dat, który chciałbym zwracać to rok-miesiąc-dzieńTgodzina:minuty:sekundy.milisekundy, czyli w bazie stringi YYYY-MM-DDTHH:mm:ss.SSS, ale... UTC, a czas lokalny... Nie wiem...

Z tego co zauważyłem są jakieś ISO, ISO 8601 stringi z sufiksami Z, +00 i inne cuda na kiju. Zapisywać daty w czasie UTC? W jakim formacie? Jak potem taki czas zwracać przez REST?

Althorion
Moderator C/C++
  • Rejestracja:prawie 10 lat
  • Ostatnio:około 20 godzin
  • Postów:1601
2

Jak właściwie zawsze, sprawa się rozbija o to, czego tak naprawdę potrzebujesz — jak często musisz zwracać datę (w odróżnieniu od wykonywania obliczeń typu „jaka jest różnica pomiędzy tymi dwoma datami”), ile masz różnych stref czasowych i jak często musisz coś przeliczać między nimi…

Jak masz jakąś bazę SQL-ową, to one mają swój typ pola do przechowywania daty i nie ma z tym specjalnie co walczyć. Jak jesteś pewien, że Cię interesuje prawie zawsze jedna strefa czasowa i ta strefa się nie zmieni (np. to są dane zamówień w sklepie internetowym — bardzo mała szansa, że przeniesiesz backend do innej strefy, żeby Cię to nagle zaczęło obchodzić), to możesz trzymać czas lokalny, ale tak czy owak sugerowałbym UTC, żeby nie mieć problemów z czasem letnim.

A jak klepiesz coś swojego, to zazwyczaj zamiast trzymania stringów bardziej użyteczne będzie trzymanie liczby sekund od 1970-01-01 i operowanie na tym.

AK
  • Rejestracja:ponad 6 lat
  • Ostatnio:około rok
  • Postów:3561
10

Dat się NIE ZAPISUJE w bazie jako string, ale jako typ datowy
Podobnie jako to jakiś język wyjmuje z bazy i przetwarza, też w typie datowym

Formatuje się do stringa tylko na zakończeniach, czy jak się SERIALIZUJE do API, czy output dla człowieka


Bo C to najlepszy język, każdy uczeń ci to powie
edytowany 1x, ostatnio: AnyKtokolwiek
AK
BTW najbardziej debilny zapis daty w bazie, jaki widziałem (na SO), to po amerykańsku. Ale nadużywanie hamburgerów swoje robi
RE
@AnyKtokolwiek: nie doprecyzowałem pytania, wiem że dla pewnych baz relacyjnych daty mają swoje DATE lub DATETIME, jednak dla sqlite nie ma takiego typu do dat :P Dlatego pytanie tyczy się tego, jaki string warto przechowywać, a może liczbę sekund, czy ma być UTC...
Roman Mokrzan
Co ty gadasz, oczywiście że jako string
KamilAdam
  • Rejestracja:ponad 6 lat
  • Ostatnio:12 dni
  • Lokalizacja:Silesia/Marki
  • Postów:5505
5
AnyKtokolwiek napisał(a):

Dat się NIE ZAPISUJE w bazie jako string, ale jako typ datowy

Podobnie jako to jakiś język wyjmuje z bazy i przetwarza, też w typie datowym

@revenger nie powiedziałeś czego używasz, ale rozwijając wypowiedź @AnyKtokolwiek

  • Przykład bazy danych - Typy daty i czasu używane w Posgresie Date/Time Types
  • Przykład języka - Typy do daty i czasu używane w Javie Package java.time (Wyjątkowo w Javie zrobili to dobrze, bo wzorowali się na bibliotece Joda Time)

Mama called me disappointment, Papa called me fat
Każdego eksperta można zastąpić backendowcem który ma się douczyć po godzinach. Tak zostałem ekspertem AI, Neo4j i Nest.js . Przez mianowanie
edytowany 1x, ostatnio: KamilAdam
RE
Chcę użyć bazy sqlite dla której nie ma DATETIME lub DATE. Ogólnie użyję UTC zgodnie z propozycjami użytkowników, lecz teraz kolejny dylemat: jak to przechować? String, liczba sekund od 1970?
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 5 godzin
  • Postów:3277
6

Jedyny sensowny sposób trzymania daty w relacyjnej bazie danych to Timestamp/Date / Datetime / Time / Interval. Moim zdaniem najsensowniej jest trzymać wszystko w UTC. W każdym innym przypadku wpakujesz się w piekło. Prezentować użytkownikowi możesz jak chcesz, zmienić strefę czasową też zawsze można na taką, która jest dogodna dla użytkownika. Nie jestem w stanie wymyślić powodu do trzymania daty łącznie ze strefą czasową.
Trzymanie dat w char / varchar świadczy o upośledzeniu w stopniu znacznym. Proste znalezienie rekordów z zeszłego roku robi się mission impossible, bo najpierw będziesz się użerać z napisaniem zapytania, później z jego wydajnością, a na koniec się okaże, że ktoś gdzieś jednak wpisał w innym formacie i zapytanie się wywala na twarz.
UTC ma wielką zaletę - brak czasu letniego / zimowego, korekt, zastanawiania się, czy godzina jest już po, czy przed zmianą czasu.

AK
W szerszym sensie, chore jest przechowywanie czegokolwiek z nastawieniem pod formatowanie (obok wątek o prostym integerze jako 'rok')
piotrpo
@AnyKtokolwiek: https://www.techopedia.com/definition/31876/stringly-typed Czyli tak jak koza wszystko zeżre, tak string wszystko przyjmie.
RE
Właśnie chodziło mi czy ma być UTC, czy nie... Aaa co zrobić jak bazka nie ma Datetime lub Date? Np. sqlite nie ma takiego typu. Wtedy co polecasz?
piotrpo
Tak jak każe dokumentacja: INTEGER jako DateTime, REAL jako Date Przynajmniej da się je porównać za pomocą normalnych operatorów, założyć sensowny indeks itd.
RE
@piotrpo: Dobrze, doczytam i spróbuję zapisać w tym formacie :D
piotrpo
https://www.sqlite.org/datatype3.html Możliwe jest też przechowywanie jako tekst, ale z powodów opisanych wyżej - nie polecam.
RE
Właśnie aktualnie przechowywałem jako TEXT (moja odpowiedź z obrazkiem), ale osobiście nie miałem do tego przekonania i trochę irytuje mnie +00 i robienie fikołków w Node. Np. w C# daty zapisywane są jeszcze inaczej i przez co szukam "uniwersalnych" sposobów. Bo faktycznie formatowanie dat można zrobić po stronie klienta.
piotrpo
Trzymając w tekście, robiąc dowolną operację (porównanie, przesunięcie o jakiś interwał itd.) najpierw przekształcić to na timestamp, później wykonać operację, na koniec wrócić do tekstu i zapisać - nie ma sensu się tak bawić.
somekind
@revenger: Co masz na myśli? W C# daty to liczba 100nanosekundowych tyknięć począwszy od 1 stycznia 1 roku naszej ery. Tak czy owak jest to po prostu long.
hauleth
Moderator
  • Rejestracja:około 17 lat
  • Ostatnio:4 dni
5

Moim zdaniem najsensowniej jest trzymać wszystko w UTC.

Otóż nie zawsze. Przykładowo jeśli przechowujesz np. godziny spotkań w jakimś miejscu (ze spotkaniami on-line jest trudniej) to przechowujesz je w postaci daty w czasie lokalnym bez strefy. Bo jeśli chcesz się spotkać o 16:00, to chcesz się spotkać o 16:00 a nie o 15:00 bo w międzyczasie zmieniła się strefa czasowa.


ZI
  • Rejestracja:około 4 lata
  • Ostatnio:ponad 3 lata
  • Postów:208
2

@hauleth: Ze spotkaniami online jest ciekawie bo musisz dorzucić strefę czasową albo jej odpowiednik, a ta może być zapisana na dwa sposoby:

  • zły sposób, z offsetem (np UTC+02:00), zły bo jak zmienią się np reguły DST to nie przeliczysz tego chyba że manualnie zaaplikujesz zmiany (czego nikt nie robi)
  • lepszy sposób, z lokalizacją głównej osoby, np Europe/Warsaw - minus tego rozwiązania jest taki że w przypadku rozpadu krajów i wojen domowych w teorii jesteś to w stanie obsłużyć, o ile przewidziałeś że np Rzeszów ogłosi niepodległość; minus jest taki że lista i forma takich stref czasowych jest niekompatybilna między różnymi środowiskami

Stąd generalnie ma się trzy rodzaje czasów:

  • lokalny
  • z offsetem
  • z zoną

i trzeba zwrócić uwagę jak to jest przeliczane na interfejsach, np z różnymi bazami danych

piotrpo
Problem z lokalizacją jest taki, że jak jakiś kraj, tak jak Rosja zrezygnuje z DST, to musisz wydać nową wersję systemu, żeby uaktualnić biblioteki do czasu.
ZI
@piotrpo: w wielu przypadkach wystarczy podbicie runtime albo tzdata, więc da się to załatwić automatem jak wyjdzie coś nowego - ale faktycznie trzeba to zrobić
piotrpo
Jest jeszcze jedno "ale" związane z przesunięciem DST - nie masz pewnych godzin, a inne godziny są niejednoznaczne (występują 2 razy w ciągu doby).
piotrpo
  • Rejestracja:ponad 7 lat
  • Ostatnio:około 5 godzin
  • Postów:3277
3

@hauleth: Jak osoba A i osoba B mają się spotkać, to muszą trafić "gdzieś" w tym samym momencie (instant). Nie ważne czy posługują się strefą UTC, CET, PST, czy tą przesuniętą o jeden dzień na Pacyfiku, bo chcieli mieć wcześniej Sylwestra. W tym momencie, w Greenwich będzie jakaś godzina (powiedzmy "uniwersalna"). Nauczyłem się myśleć o strefie czasowe jak o formacie daty - jedni wolą format od dnia, inni od roku, a jeszcze inni amerykański.

Dość ostro przećwiczyłem te opcje robiąc system do umawiania spotkań (albo to daty mnie ostro przećwiczyły), ciężko będzie mnie przekonać :) W sumie czas lokalny ma znaczenie w jednym przypadku - kiedy zależy ci na wiedzy jak daną sytuację postrzega jakiś użytkownik / obiekt. Np. nie chcesz umawiać spotkań gdzie którykolwiek użytkownik będzie musiał się wdzwonić o 4:00

RE
  • Rejestracja:około 4 lata
  • Ostatnio:ponad 3 lata
  • Postów:66
0

Sory, mogłem jeszcze dopisać, że jak to wygląda w kontekście bazki sqlite dla której nie ma DATE lub DATETIME... Z racji, że bawię się SequelizeORM, to domyślnie zapisuje mi do bazki czas UTC w formacie jak poniżej. Nie wiem co myśleć :P Dobre? Tragiczne?

czas.png

piotrpo
Napisz zapytanie zwracające wynik posortowany po date. Albo takie które zwraca jedynie ostatnie 10 minut.
Shalom
  • Rejestracja:około 21 lat
  • Ostatnio:prawie 3 lata
  • Lokalizacja:Space: the final frontier
  • Postów:26433
6

Dokumentacja mówi żeby uzywać TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS"). bo spina się wtedy automatycznie z funkcjami do obsługi dat w sqlite i tego bym się trzymał.


"Nie brookliński most, ale przemienić w jasny, nowy dzień najsmutniejszą noc - to jest dopiero coś!"
edytowany 1x, ostatnio: Shalom
somekind
Jaka dokumentacja, co Ty chcesz narodową tradycję kombinowania zniszczyć? :D
piotrpo
https://www.sqlite.org/datatype3.html Dokumentacja (przynajmniej w tym fragmencie) proponuje użycie timestampów na równi z formatowanym stringiem
Shalom
No tak, ale kolega chciał stringa więc zasugerowałem zeby użył formatu stringa który sqlite ogarnia :)
RE
Niekoniecznie musiał być string, po prostu szukałem dobrego sposobu na przechowywanie "czasu". Czas UTC i UNIX timestamp wydają się spoko. Na razie działa.
Marcin Marcin
  • Rejestracja:prawie 6 lat
  • Ostatnio:17 dni
  • Postów:610
4


Fan moderatora somekind
AK
Uprzedziłeś mnie
Marcin Marcin
Twój system nie osiągnął dna jeżeli nie posiada własnego parsera dat.
Roman Mokrzan
  • Rejestracja:ponad 5 lat
  • Ostatnio:około 2 miesiące
  • Postów:159
0

Epoch time


Kliknij, aby dodać treść...

Pomoc 1.18.8

Typografia

Edytor obsługuje składnie Markdown, w której pojedynczy akcent *kursywa* oraz _kursywa_ to pochylenie. Z kolei podwójny akcent **pogrubienie** oraz __pogrubienie__ to pogrubienie. Dodanie znaczników ~~strike~~ to przekreślenie.

Możesz dodać formatowanie komendami , , oraz .

Ponieważ dekoracja podkreślenia jest przeznaczona na linki, markdown nie zawiera specjalnej składni dla podkreślenia. Dlatego by dodać podkreślenie, użyj <u>underline</u>.

Komendy formatujące reagują na skróty klawiszowe: Ctrl+B, Ctrl+I, Ctrl+U oraz Ctrl+S.

Linki

By dodać link w edytorze użyj komendy lub użyj składni [title](link). URL umieszczony w linku lub nawet URL umieszczony bezpośrednio w tekście będzie aktywny i klikalny.

Jeżeli chcesz, możesz samodzielnie dodać link: <a href="link">title</a>.

Wewnętrzne odnośniki

Możesz umieścić odnośnik do wewnętrznej podstrony, używając następującej składni: [[Delphi/Kompendium]] lub [[Delphi/Kompendium|kliknij, aby przejść do kompendium]]. Odnośniki mogą prowadzić do Forum 4programmers.net lub np. do Kompendium.

Wspomnienia użytkowników

By wspomnieć użytkownika forum, wpisz w formularzu znak @. Zobaczysz okienko samouzupełniające nazwy użytkowników. Samouzupełnienie dobierze odpowiedni format wspomnienia, zależnie od tego czy w nazwie użytkownika znajduje się spacja.

Znaczniki HTML

Dozwolone jest używanie niektórych znaczników HTML: <a>, <b>, <i>, <kbd>, <del>, <strong>, <dfn>, <pre>, <blockquote>, <hr/>, <sub>, <sup> oraz <img/>.

Skróty klawiszowe

Dodaj kombinację klawiszy komendą notacji klawiszy lub skrótem klawiszowym Alt+K.

Reprezentuj kombinacje klawiszowe używając taga <kbd>. Oddziel od siebie klawisze znakiem plus, np <kbd>Alt+Tab</kbd>.

Indeks górny oraz dolny

Przykład: wpisując H<sub>2</sub>O i m<sup>2</sup> otrzymasz: H2O i m2.

Składnia Tex

By precyzyjnie wyrazić działanie matematyczne, użyj składni Tex.

<tex>arcctg(x) = argtan(\frac{1}{x}) = arcsin(\frac{1}{\sqrt{1+x^2}})</tex>

Kod źródłowy

Krótkie fragmenty kodu

Wszelkie jednolinijkowe instrukcje języka programowania powinny być zawarte pomiędzy obróconymi apostrofami: `kod instrukcji` lub ``console.log(`string`);``.

Kod wielolinijkowy

Dodaj fragment kodu komendą . Fragmenty kodu zajmujące całą lub więcej linijek powinny być umieszczone w wielolinijkowym fragmencie kodu. Znaczniki ``` lub ~~~ umożliwiają kolorowanie różnych języków programowania. Możemy nadać nazwę języka programowania używając auto-uzupełnienia, kod został pokolorowany używając konkretnych ustawień kolorowania składni:

```javascript
document.write('Hello World');
```

Możesz zaznaczyć również już wklejony kod w edytorze, i użyć komendy  by zamienić go w kod. Użyj kombinacji Ctrl+`, by dodać fragment kodu bez oznaczników języka.

Tabelki

Dodaj przykładową tabelkę używając komendy . Przykładowa tabelka składa się z dwóch kolumn, nagłówka i jednego wiersza.

Wygeneruj tabelkę na podstawie szablonu. Oddziel komórki separatorem ; lub |, a następnie zaznacz szablonu.

nazwisko;dziedzina;odkrycie
Pitagoras;mathematics;Pythagorean Theorem
Albert Einstein;physics;General Relativity
Marie Curie, Pierre Curie;chemistry;Radium, Polonium

Użyj komendy by zamienić zaznaczony szablon na tabelkę Markdown.

Lista uporządkowana i nieuporządkowana

Możliwe jest tworzenie listy numerowanych oraz wypunktowanych. Wystarczy, że pierwszym znakiem linii będzie * lub - dla listy nieuporządkowanej oraz 1. dla listy uporządkowanej.

Użyj komendy by dodać listę uporządkowaną.

1. Lista numerowana
2. Lista numerowana

Użyj komendy by dodać listę nieuporządkowaną.

* Lista wypunktowana
* Lista wypunktowana
** Lista wypunktowana (drugi poziom)

Składnia Markdown

Edytor obsługuje składnię Markdown, która składa się ze znaków specjalnych. Dostępne komendy, jak formatowanie , dodanie tabelki lub fragmentu kodu są w pewnym sensie świadome otaczającej jej składni, i postarają się unikać uszkodzenia jej.

Dla przykładu, używając tylko dostępnych komend, nie możemy dodać formatowania pogrubienia do kodu wielolinijkowego, albo dodać listy do tabelki - mogłoby to doprowadzić do uszkodzenia składni.

W pewnych odosobnionych przypadkach brak nowej linii przed elementami markdown również mógłby uszkodzić składnie, dlatego edytor dodaje brakujące nowe linie. Dla przykładu, dodanie formatowania pochylenia zaraz po tabelce, mogłoby zostać błędne zinterpretowane, więc edytor doda oddzielającą nową linię pomiędzy tabelką, a pochyleniem.

Skróty klawiszowe

Skróty formatujące, kiedy w edytorze znajduje się pojedynczy kursor, wstawiają sformatowany tekst przykładowy. Jeśli w edytorze znajduje się zaznaczenie (słowo, linijka, paragraf), wtedy zaznaczenie zostaje sformatowane.

  • Ctrl+B - dodaj pogrubienie lub pogrub zaznaczenie
  • Ctrl+I - dodaj pochylenie lub pochyl zaznaczenie
  • Ctrl+U - dodaj podkreślenie lub podkreśl zaznaczenie
  • Ctrl+S - dodaj przekreślenie lub przekreśl zaznaczenie

Notacja Klawiszy

  • Alt+K - dodaj notację klawiszy

Fragment kodu bez oznacznika

  • Alt+C - dodaj pusty fragment kodu

Skróty operujące na kodzie i linijkach:

  • Alt+L - zaznaczenie całej linii
  • Alt+, Alt+ - przeniesienie linijki w której znajduje się kursor w górę/dół.
  • Tab/⌘+] - dodaj wcięcie (wcięcie w prawo)
  • Shit+Tab/⌘+[ - usunięcie wcięcia (wycięcie w lewo)

Dodawanie postów:

  • Ctrl+Enter - dodaj post
  • ⌘+Enter - dodaj post (MacOS)