Pomoc - Szukaj - Użytkownicy - Kalendarz
Pełna wersja: [Data] Formatowanie daty i czasu
Forum PHP.pl > Forum > PHP
WebCM
Aktualnie przechowuję datę w formacie datetime w MySQL bądź SQLite. Jest jednak problem. Data jest sztywna - przystosowana tylko dla 1 strefy czasowej.

Funkcja formatująca datę:
http://www.unit1.pl/pb-806

1. Datę można przechowywać jako timestamp. Wtedy w PHP formatujemy ją za pomocą strftime() lub date(), podając znacznik czasu jako drugi parametr.

2. Jeśli news został napisany dzisiaj, zamiast daty powinien wyświetlić się napis "Dzisiaj". W przypadku użycia timestamp raczej nie będzie to łatwe. Gdy datę przechowujemy jako datetime - odsyłam do kodu (link wyżej). smile.gif

Zależy mi przede wszystkim na wydajności odczytu i formatowania daty i czasu. Co możecie doradzić?

PS. Pamiętajcie, że czasem czas jest zbędny (ważna tylko data).
phpion
Ja osobiście wolę stosować pole typu DATETIME zamiast TIMESTAMP. Bardzo często przeglądam zawartość bazy danych korzystając z MySQL Query Browser czy chociażby phpMyAdmin i mając daty w formacie DATETIME od razu wiem, jaka data kryje się pod danym polem. Mając zamiast tego znacznik TIMESTAMP raczej ciężko by mi było zajarzyć co do za data i godzina smile.gif hehe.
nevt
zdecydowanie zostań przy typie danych DATETIME. formatowanie, zmianę strefy czasowej i zamianę na napis "Dzisiaj" załatwiaj po stronie MySQL a nie w JS. tak będzie najszybciej i najwydajniej, poszukaj w manualu MySQL opisów do funkcji:

DATE_FORMAT( ... )
CONVERT_TZ( ... )
CURDATE( ... )

powodzenia.
merk
Dla pola daty zazwyczaj korzystam z DATETIME lub DATE, a formatuję je za pomocą funkcji
strtotime(); lub mktime(); i date();
WebCM
Można też rozbić datę za pomocą explode() i użyć mktime(). Tylko czy jest sens zamieniać format YYYY-MM-DD na znacznik czasu i z powrotem (bo funkcja strftime() musi to zrobić)?

Chyba, że elastyczność daty nie jest na tyle istotna i wystarczy zapisywać ją do bazy w strefie czasowej zgodnej z wybranym językiem (np. kilka godzin wstecz dla USA).

PS. PHP 5.1 wniósł nowe funkcje daty, w tym obiektowe. Muszę jeszcze poeksperymentować.
Pilsener
A ja używam daty w postaci uniksowej - przyzwyczaiłem się tati jest tak wygodnie, bo (chyba?) każda funkcja respektuje ten format daty.
WebCM
Zostańmy jeszcze przy formacie YYYY-MM-DD HH:MM:SS (datetime). Przypominam, że skrypt musi być zgodny zarówno z MySQL oraz SQLite (bez pisania 2 zapytań).

Zobacz kod: http://www.unit1.pl/pb-813 - funkcja przyjmuje datę dla strefy GMT. Jeśli jest taka sama jak dzisiaj, wyświetla napis "Dzisiaj". Jest 1 problem. Nie uwzględnia stref czasowych.

Jak dostosować datę do strefy czasowej użytkownika? Czy zamiana na timestamp() i z powrotem do czytelnego formatu jest jedynym wyjściem (np. strtotime() + date() lub obiekt DateTime)? Można też pewnie rozwiązać problem matematycznie (więcej z tym zabawy). Czy ktoś już zmagał się ze strefami czasowymi?

Gdybym przechowywał znaczniki czasu (timestamp) zamiast pełnych dat (datetime), PHP automatycznie poradzi sobie ze strefami czasowymi, lecz za to wyświetlanie "Dzisiaj", "Jutro" stanie się trudniejsze.

nevt: świetnie, że MySQL oferuje takie funkcje, lecz brakuje ich w SQLite bądź mają inne nazwy. Lepiej formatować datę w PHP i być niezależnym od silnika SQL.
nevt
przecież pomoc masz jak na dłoni. nie potrzebuję twojego pomógł, ale przecież 6 postów wyżej masz na tacy podane rozwiązanie. wystarczy zajrzeć do jakiegokolwiek manuala MySQL5 żeby sprawdzić, że:

DATE_FORMAT( ... ) - formatuje ci wyświetlanie daty tak jak sobie życzysz...
CONVERT_TZ( ... ) - dopasowuje ci datę i czas do określonej strefy czasowej (Time Zone)
CURDATE( ... ) - zwraca ci bieżącą datę, co w połączeniu z IF( ... ) umożliwia prostą generację napisu "Dzisiaj" ...

a wszystko bezpośrednio w MySQL - bez żadnych dodatków w skrypcie PHP - nie wymyślisz optymalniejszego i wydajniejszego mechanizmu...
WebCM
Co z tego, że MySQL oferuje takie funkcje, jeżeli brakuje ich w SQLite lub mają inne nazwy? Przypominam, że skrypt być zgodny z tymi 2 silnikami SQL. Aby osiągnąć efekt, musiałbym dodawać wstawki lub funkcje generujące fragment zapytania do bazy, aby pobrać właściwie sformatowaną datę. A gdy dodam obsługę kolejnego silnika?

Jest jeszcze 1 wyjście - funkcje w SQL. Definiowałoby się je przy połączeniu bądź na żądanie. Osobny kod dla MySQL i SQLite. Nie wiem, jak to przełoży się na wydajność, bo trzeba wysłać dodatkowe zapytanie.

Co w takim razie radzicie? Formatowanie daty po stronie PHP czy SQL?
Pilsener
PHP. Użyj funkcji setlocale i date_default_timezone_set, żeby dostosować język i strefę czasową.
WebCM
Na strftime() lub date() ze znacznikiem czasowym pomaga tylko date_default_timezone_set(). Może ustawiam złą lokalizację w setlocale() na localhost (WinXP)? Wracając do formatowania daty - potrzebuję wskazówek. W tym przypadku wydajność jest istotna. smile.gif Szczególnie, gdy trzeba wygenerować N dat.

Podsumowując:
1. Czy konieczna jest zamiana daty na timestamp?
2. Jak przechowywać datę w bazie, aby osiągnąć najlepszą wydajność? INT czy DATETIME? Martwić się o 2038?
3. Formatować datę po stronie PHP czy SQL?

Efekty, które muszę uzyskać:
1. "5 minut temu"
2. Data we właściwej strefie czasowej (ustawionej przez użytkownika)
3. "23.05.2008, 12:23" (jeśli ustawiono taki format daty), opcjonalnie: "23 May 2008 o 12:23"
4. "Dzisiaj o 12:23"

Skrypt obsługuje bazy SQLite i MySQL. Aby formatować datę po stronie bazy, prawdopodobnie muszę tworzyć przy połączeniu (lub na żądanie) funkcję do tego celu - osobno dla każdego z tych silników.

Wykonałem pomiar szybkości odczytu rekordów z datą zawierającą się w określonym przedziale czasu. http://www.unit1.pl/pb-817

Różnica jest prawie niezauważalna, jednak pola INT nieznacznie wygrywają. smile.gif

Gdybyśmy jednak chcieli wyświetlić wszystkie rekordy dodane w roku 2008 lub w maju 2007 - z użyciem funkcji MONTH(), której brakuje w SQLite, pewnie wygrałby typ DATETIME. Można też wygenerować znaczniki czasu dla tych 2 punktów w PHP (godz. 0:00 GMT, 1 stycznia) - gmmktime() lub pochodna.

PHP opiera się głównie o znaczniki czasu, a nie YYYY-MM-DD. sad.gif Funkcje typu strtotime() pełnią rolę pomocniczą.
dragonsokol
int..
zapisujesz czas GMT i dodajesz w sekundach bodajze roznice strefowa
np +1: GMT+(3600);
Pilsener
Cytat
Może ustawiam złą lokalizację w setlocale() na localhost (WinXP)?

Prawdopodobnie tak. Poeksperymentuj z czymś w rodzaju:
  1. <?php
  2. $arrLocale = array( "pl_PL", "polish_pol" );
  3. setlocale(LC_ALL, $arrLocale );
  4. ?>
- może nie działać na wszystkich serwerach.

Cytat
Czy konieczna jest zamiana daty na timestamp?
- tak czy inaczej nie unikniesz zamiany datetime na timestamp w skrypcie, a datę (obojętnie datetime czy timestamp) i tak musisz formatować. Konieczne to nie jest, specjalnie nie ma też pewnie wpływu na wydajność, ale moim zdaniem wygodne.

Musisz się na coś zdecydować - ważne, że jak zdecydujesz się na taki czy owaki format daty, to musisz tego konsekwentnie używać wszędzie. Ja bym się skłaniał ku int - dla mnie ten format daty jest prostszy i bardziej logiczny a formatowanie i "obrabianie" daty po stronie PHP przecież nie sprawia problemów z wydajnością - zresztą twórcy PHP chyba też tak sądzą, bo wyraźnie preferują timestamp.

Cytat
...z użyciem funkcji MONTH(), której brakuje w SQLite, pewnie wygrałby typ DATETIME
- nie byłbym taki pewien - integery chodzą jak burza smile.gif

Poza tym baza jest często na innym serwerze no i jak dla mnie baza to baza, ma przechowywać dane, a nie je obrabiać.
WebCM
Problemów ciąg dalszy. Okazuje się, że w PHP brakuje funkcji gmtime(). Wprawdzie aktualny znacznik czasu dla GMT można uzyskać tak: time() - date('Z'), ale po co kombinować? Pomaga też date_default_timezone_set('GMT').

Czy jest w takim razie sens zapisywać wszystkie czasy do bazy danych w GMT? Czy lepiej w strefie lokalnej dla danego języka? Co o tym myślicie?

Funkcja formatująca datę - jeszcze niekompletna: http://rafb.net/p/yZsVSa57.html

Wypełnijcie ankietę: Problem daty w PHP i systemach CMS
To jest wersja lo-fi głównej zawartości. Aby zobaczyć pełną wersję z większą zawartością, obrazkami i formatowaniem proszę kliknij tutaj.
Invision Power Board © 2001-2025 Invision Power Services, Inc.