[php] naar de volgende dag

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • mjax
  • Registratie: September 2000
  • Laatst online: 10:03
Ik loop in m'n code vaak tegen de noodzaak aan om op basis van een PHP datum de volgende dag te bepalen. Hiervoor gebruik ik meestal:

PHP:
1
$cur_date = mktime(0, 0, 0, date('m', $cur_date), date('d', $cur_date)+1, date('Y', $cur_date));


Deze code heeft overigens een bug in de nieuwste PHP versie (4.3.5), die ik al gemeld heb op bugs.php.net.

Los daarvan, zijn er standaard functies om naar de volgende dag te gaan?

Uiteraard is
PHP:
1
$cur_date += 86400
geen optie, aangezien je hiermee in de problemen kunt komen i.v.m. zomer/wintertijd. M.a.w. je komt dan wel (of in de nieuwste versie dus NIET) op de volgende dag uit, maar niet op 00:00:00.

Ik zoek dus eigenlijk een betrouwbare manier om op basis van een PHP datum (inclusief tijd) te gaan naar de volgende dag, op diezelfde tijd.

Acties:
  • 0 Henk 'm!

  • supakeen
  • Registratie: December 2000
  • Laatst online: 09-09 14:42
PHP:
1
2
3
<?php
$nextday = time() + 24 * 3600;
?>

Acties:
  • 0 Henk 'm!

  • faabman
  • Registratie: Januari 2001
  • Laatst online: 08-08-2024
1ste resultaat op google
http://www.phpbuilder.com/columns/akent20000610.php3?page=6

met zoekopdracht
[google=php dateadd]

Op zoek naar een baan als Coldfusion webdeveloper? Mail me!


Acties:
  • 0 Henk 'm!

  • Spider.007
  • Registratie: December 2000
  • Niet online

Spider.007

* Tetragrammaton

PHP:
1
echo strtotime("+1 day"), "\n";

[ Voor 18% gewijzigd door Spider.007 op 27-03-2004 21:01 ]

---
Prozium - The great nepenthe. Opiate of our masses. Glue of our great society. Salve and salvation, it has delivered us from pathos, from sorrow, the deepest chasms of melancholy and hate


Acties:
  • 0 Henk 'm!

  • mjax
  • Registratie: September 2000
  • Laatst online: 10:03
zmn schreef op 27 maart 2004 @ 20:59:
PHP:
1
2
3
<?php
$nextday = time() + 24 * 3600;
?>
Dit is dus precies hetzelfde als:
PHP:
1
$cur_date += 86400;


@faabman:

Dat is helaas geen ingebouwde PHP functie en maakt nog steeds gebruik van mktime(). Ik had in mijn OP niet aangegeven dat ik op zoek ben naar een (al dan niet ingebouwde) functie die NIET gebruik maakt van mktime().

@Spider.007

Leuk! Maar werkt alleen voor "vandaag" naar "morgen", niet voor een willekeurige PHP datum, tenzij je die in strtotime() kunt stoppen in Engels tekst formaat (wat overkill voor mijn situatie zou zijn).

Ik denk dat ik op basis van de DateAdd() functie die voorgesteld is door faabman, een versie ga maken zie GEEN rekening houdt met zomer/wintertijd (want in essentie is dat dus het probleem).

UPDATE: Ik heb ontdekt dat gmmktime() GEEN rekening houdt met zomer/wintertijd en dus precies doet wat ik wil. Echter, als ik de usernotes bij die functie moet geloven is gmmktime() nog erger dan mktime() qua bugs, maar dan op andere vlakken... Hmm...

[ Voor 15% gewijzigd door mjax op 27-03-2004 21:38 ]


Acties:
  • 0 Henk 'm!

Verwijderd

waarom gebruik je niet unixtime en doe je + het aantal seconden dat een dag duurt? en dan parsen ?

Acties:
  • 0 Henk 'm!

  • JER00N
  • Registratie: Maart 2002
  • Niet online
Ik denk dat je het best gebruik kan maken van microtime ( = het aantal seconden na 1-1-1970). Met date() kan je die microtime vervolgens in elk denkbaar formaat parsen. Bovendien kan je er makkelijk één dag bij optellen: $morgen = $microtime + 86400

microtime: http://www.php.net/microtime
date: http://www.php.net/date

voorbeeldje:
de microtime 'op dit moment' is $microtime.
PHP:
1
echo "Vandaag is het " . date("d-m-Y", $microtime) . ", en morgen is het " . date("d-m-Y", $microtime + 86400);

Acties:
  • 0 Henk 'm!

  • mjax
  • Registratie: September 2000
  • Laatst online: 10:03
Verwijderd schreef op 27 maart 2004 @ 21:31:
waarom gebruik je niet unixtime en doe je + het aantal seconden dat een dag duurt? en dan parsen ?
Bedoel je hiermee een commandline aanroep en de resultaten hiervan parsen? Gaat niet werken, want het moet platform onafhankelijk blijven (Windows en FreeBSD).

Acties:
  • 0 Henk 'm!

  • mjax
  • Registratie: September 2000
  • Laatst online: 10:03
Pastasaus schreef op 27 maart 2004 @ 21:33:
Ik denk dat je het best gebruik kan maken van microtime ( = het aantal seconden na 1-1-1970). Met date() kan je die microtime vervolgens in elk denkbaar formaat parsen. Bovendien kan je er makkelijk één dag bij optellen: $morgen = $microtime + 86400

microtime: http://www.php.net/microtime
date: http://www.php.net/date

voorbeeldje:
de microtime 'op dit moment' is $microtime.
PHP:
1
echo "Vandaag is het " . date("d-m-Y", $microtime) . ", en morgen is het " . date("d-m-Y", $microtime + 86400);
Mooie oplossing, maar het werkt (zover ik dat nu kan zien) niet voor elke willekeurige datum, omdat het gebaseerd is op de lokale systeemtijd. Ik moet dus ook voor een datum in het verleden en in de toekomst de volgende dag kunnen bepalen.

Maar zoals gezegd, ga ik verder aan de slag met gmmktime() want tot nu toe zien de resultaten van mijn tests er veelbelovend uit!

Acties:
  • 0 Henk 'm!

Verwijderd

PHP:
1
2
3
$today = time( );
$tomorrow = $today + 86400;
$tomorrow -= $tomorrow % 86400;


Zoiets als dit gebruik ik meestal.

Acties:
  • 0 Henk 'm!

  • PrisonerOfPain
  • Registratie: Januari 2003
  • Laatst online: 26-05 17:08
mjax schreef op 27 maart 2004 @ 21:40:
[...]


Bedoel je hiermee een commandline aanroep en de resultaten hiervan parsen? Gaat niet werken, want het moet platform onafhankelijk blijven (Windows en FreeBSD).
een unix timestamp is gewoon het aantal seconden verstreken sinds de unix epoch op 0-0-1970, te achterhalen met time();

Acties:
  • 0 Henk 'm!

  • Soultaker
  • Registratie: September 2000
  • Laatst online: 20-09 18:51
Leuk dat dit topic er juist vandaag staat, want dat geeft een mooie illustratie waarom het optellen van 86400 seconden eigenlijk niet waterdicht is. Zondag treedt de zomertijd in werking en dus bevat zondag maar 23 uur (in plaats van 24). Als ik dus vanavond om half twaalf het script van Pastasaus uitvoer, dan zal die zeggen dat het vandaag 27 maart is en morgen (eigenlijk '24 uur later') 29 maart! Dat klopt dus niet.

Hoewel het praktisch onmogelijk is om het altijd goed te doen, is het gebruik van mktime een stuk verstandiger. De implementatie in PHP is speciaal gemaakt voor het rekenen met data en corrigeert automatisch data die buiten goede grenzen valt. Een verstandige oplossing is dus het gebruik van localtime om eerst de huidige dag in componenten op te splitsen en vervolgens met mktime een nieuwe timestamp te construeren.
PHP:
1
2
3
4
5
6
7
$now = time();
echo 'Today: ', date('r', $now), '<br/>';

$today = getdate($now);
$tomorrow = mktime( $today['hours'], $today['minutes'], $today['seconds'], 
    $today['mon'], $today['mday'] + 1, $today['year'] );
echo 'Tomorrow: ', date('r', $tomorrow), '<br/>';

Let op de expressie ($today['mday'] + 1). Je hoeft hier zelf geen moeite voor te doen om deze te corrigeren bij overgang naar de volgende maand; als het 31 maart is en je dus als 32 meegeeft als dag van de volgende maand, dan interpreteert mktime dit automatisch als eerste dag van de volgende maand.

De uitvoer wordt dan ook zoiets:
Today: Sat, 27 Mar 2004 22:12:56 +0100
Tomorrow: Sun, 28 Mar 2004 22:12:56 +0200
(Merk ook op dat de tijdzone verandert van +0100 naar +0200 omdat de klok een uur vooruit is gegaan.)

Ik kan trouwens nog wel uitgebreid vertellen over wat er allemaal mis kan gaan bij het rekenen met tijden/data gecombineerd met tijdzones, maar dat is misschien niet helemaal on-topic. Bottom line is dat je het eigenlijk nooit goed kan doen, maar je kan wel je best doen om het zo goed mogelijk te doen.

edit:
Ik zie dat ik nu vooral andere users dan mjax aan het 'helpen' ben, want mjax had dit zelf ook allemaal al geconstateerd. De bug in mktime verprutst het een beetje. Voor zover ik weet kun je het echter niet veel beter doen dan met mktime, dus dan moet je die bug maar voor lief nemen en je eigen workaround toepassen. Tenzij iemand nog betere suggesties heeft, natuurlijk. :)

[ Voor 13% gewijzigd door Soultaker op 27-03-2004 22:54 ]


Acties:
  • 0 Henk 'm!

  • mjax
  • Registratie: September 2000
  • Laatst online: 10:03
Soultaker schreef op 27 maart 2004 @ 22:16:
Leuk dat dit topic er juist vandaag staat, want dat geeft een mooie illustratie waarom het optellen van 86400 seconden eigenlijk niet waterdicht is. Zondag treedt de zomertijd in werking en dus bevat zondag maar 23 uur (in plaats van 24). Als ik dus vanavond om half twaalf het script van Pastasaus uitvoer, dan zal die zeggen dat het vandaag 27 maart is en morgen (eigenlijk '24 uur later') 29 maart! Dat klopt dus niet.

Hoewel het praktisch onmogelijk is om het altijd goed te doen, is het gebruik van mktime een stuk verstandiger. De implementatie in PHP is speciaal gemaakt voor het rekenen met data en corrigeert automatisch data die buiten goede grenzen valt. Een verstandige oplossing is dus het gebruik van localtime om eerst de huidige dag in componenten op te splitsen en vervolgens met mktime een nieuwe timestamp te construeren.
PHP:
1
2
3
4
5
6
7
$now = time();
echo 'Today: ', date('r', $now), '<br/>';

$today = getdate($now);
$tomorrow = mktime( $today['hours'], $today['minutes'], $today['seconds'], 
    $today['mon'], $today['mday'] + 1, $today['year'] );
echo 'Tomorrow: ', date('r', $tomorrow), '<br/>';

Let op de expressie ($today['mday'] + 1). Je hoeft hier zelf geen moeite voor te doen om deze te corrigeren bij overgang naar de volgende maand; als het 31 maart is en je dus als 32 meegeeft als dag van de volgende maand, dan interpreteert mktime dit automatisch als eerste dag van de volgende maand.

De uitvoer wordt dan ook zoiets:
[...]
(Merk ook op dat de tijdzone verandert van +0100 naar +0200 omdat de klok een uur vooruit is gegaan.)

Ik kan trouwens nog wel uitgebreid vertellen over wat er allemaal mis kan gaan bij het rekenen met tijden/data gecombineerd met tijdzones, maar dat is misschien niet helemaal on-topic. Bottom line is dat je het eigenlijk nooit goed kan doen, maar je kan wel je best doen om het zo goed mogelijk te doen.

edit:
Ik zie dat ik nu vooral andere users dan mjax aan het 'helpen' ben, want mjax had dit zelf ook allemaal al geconstateerd. De bug in mktime verprutst het een beetje. Voor zover ik weet kun je het echter niet veel beter doen dan met mktime, dus dan moet je die bug maar voor lief nemen en je eigen workaround toepassen. Tenzij iemand nog betere suggesties heeft, natuurlijk. :)
Goed laten we de conclusie trekken dat werken met datum/tijden in PHP tricky is. Dat was me al bekend, hoewel ik dus sinds vandaag nog wat meer eigenaardigheden ken. Ik ga aan de slag om een "veilige" versie te bouwen van een functie die datum aanpassingen kan uitvoeren, zonder last te hebben van tijdzones, zomer/wintertijd etc.

Leuk detail. De bug met mktime() in PHP 4.3.5 die ik vandaag gemeld had om 20:50, is om 22:30 al opgelost in de CVS stable build. Ik kreeg direct daarna een mailje van 1 van de ontwikkelaars om deze nieuwe versie even te testen en ja hoor, opgelost! Hij gaat dus gewoon in de volgende release 4.3.6 mee. Erg gaaf dat die ontwikkelaars hier boven op zitten!
Pagina: 1