Michel G. Posted June 24, 2013 Share Posted June 24, 2013 I'm having the following issue to build-up a liturgical calendar; the mistake is related to the daylight saving time, which adds 1h and makes my whole construction invalid: <?php $date = strtotime('09-05-2013'); echo "Date: ".$date."<br />"; // May 9th, 2013 is the effective date of Ascension //The year can be easily extracted from the date $year = date('Y', $date); echo "Year: ".$year."<br />"; // The date of Easter can be easily extracted thanks to the corresponding php-native "easter_date" function $easter = easter_date($year); // The ascension is 39 days after Easter $ascension = ($easter + (39*86400)); echo "Ascension: ".$ascension."<br />"; if ($date == $ascension) { echo "It's Ascension"; } else { echo "There is a mistake in the code"; } ?> The problem is: the date of 09-05-2013 gives a string which is 3600 sec. more than the calculated value based on Easter. What can I do to define correctly the $ascension value from Easter, knowing that the daylight saving change does not always occur every year between Easter and Ascension? Link to comment Share on other sites More sharing options...
Antonio Conte Posted June 24, 2013 Share Posted June 24, 2013 (edited) Look at the notes in the manual. As it says there, easter_date() is based on the TZ environment variable rather than the default time zone. They do attach a function to solve the problem: /** * Get Unix timestamp for midnight on Easter of a given year * * This function fixes easter_days()'s TZ environment problem */ function get_easter_datetime($year) { $days = easter_days($year); $date = new DateTime("$year-03-21"); $date->add(new DateInterval("P{$days}D")); // Get the correct timestamp from the object return $date->getTimestamp(); } Hope that helps you out. Edited June 25, 2013 by Antonio Conte Link to comment Share on other sites More sharing options...
Michel G. Posted June 25, 2013 Author Share Posted June 25, 2013 Thanks a lot for the reference to the manual, even though I need some time to master expressions like "new DateTime" or "DateInterval". Is this related to OOP? Or in the "QuickPro" guide?... Link to comment Share on other sites More sharing options...
Antonio Conte Posted June 25, 2013 Share Posted June 25, 2013 Yes, it's object oriented. That doesn't really matter in the end here, though. Both the classes used are part of PHP, so you can drop the exact (updated) code I posted into your own code and use it. You don't have to understand the underlaying logic of DateTime or DateInterval to play with them. This should give you what you want // Paste the function into your code (like below) Or require/include a file with it function get_easter_datetime($year) { $days = easter_days($year); // Create a DateTime object $date = new DateTime("$year-03-21"); // and add the number of days after March 21 // on which Easter falls for the given year $date->add(new DateInterval("P{$days}D")); // Return the result as a unix timestamp return $date->getTimestamp(); } $date = strtotime('09-05-2013'); echo "Date: ".$date."<br />"; // May 9th, 2013 is the effective date of Ascension // The year can be easily extracted from the date $year = date('Y', $date); echo "Year: ".$year."<br />"; // Work with function here $easter = get_easter_datetime($year); // The ascension is 39 days after Easter $ascension = ($easter + (39*86400)); echo "Ascension: ".$ascension."<br />"; echo ($date == $ascension) ? "It's Ascension" : "There is a mistake in the code"; Assuming your logic is sound, this should work perfectly. It's as simple as pasting the function into your project and using get_easter_datetime() instead of easter_days(). Edit: Really sorry. I didn't notice the object was returned rather than a value. I ammended the function to return a unix timestamp instead. Edit 2: Added explanatory comments to the function. Link to comment Share on other sites More sharing options...
Recommended Posts