@ Fyrye'nin çok yararlı cevabına ek olarak, bu, belirtilen hata ( bu ) için tamamlayıcı bir çözümdür, DatePeriod yaz saatine girerken bir saat kullanır, ancak yaz saatinden ayrılırken bir saat eklemez (ve dolayısıyla Avrupa / Berlin'in Mart ayının doğru 743 saat, ancak Ekim'de 745 saat yerine 744 saat var):
Her iki yöndeki DST geçişlerini göz önünde bulundurarak bir ayın (veya herhangi bir zaman aralığının) saatlerini saymak
function getMonthHours(string $year, string $month, \DateTimeZone $timezone): int
{
// or whatever start and end \DateTimeInterface objects you like
$start = new \DateTimeImmutable($year . '-' . $month . '-01 00:00:00', $timezone);
$end = new \DateTimeImmutable((new \DateTimeImmutable($year . '-' . $month . '-01 23:59:59', $timezone))->format('Y-m-t H:i:s'), $timezone);
// count the hours just utilizing \DatePeriod, \DateInterval and iterator_count, hell yeah!
$hours = iterator_count(new \DatePeriod($start, new \DateInterval('PT1H'), $end));
// find transitions and check, if there is one that leads to a positive offset
// that isn't added by \DatePeriod
// this is the workaround for https://bugs.php.net/bug.php?id=75685
$transitions = $timezone->getTransitions((int)$start->format('U'), (int)$end->format('U'));
if (2 === count($transitions) && $transitions[0]['offset'] - $transitions[1]['offset'] > 0) {
$hours += (round(($transitions[0]['offset'] - $transitions[1]['offset'])/3600));
}
return $hours;
}
$myTimezoneWithDST = new \DateTimeZone('Europe/Berlin');
var_dump(getMonthHours('2020', '01', $myTimezoneWithDST)); // 744
var_dump(getMonthHours('2020', '03', $myTimezoneWithDST)); // 743
var_dump(getMonthHours('2020', '10', $myTimezoneWithDST)); // 745, finally!
$myTimezoneWithoutDST = new \DateTimeZone('UTC');
var_dump(getMonthHours('2020', '01', $myTimezoneWithoutDST)); // 744
var_dump(getMonthHours('2020', '03', $myTimezoneWithoutDST)); // 744
var_dump(getMonthHours('2020', '10', $myTimezoneWithoutDST)); // 744
Not: Bu iki geçişten daha fazlasına yol açan (daha uzun) bir zaman aralığını kontrol ederseniz, benim geçici çözümüm, komik yan etkilerin potansiyelini azaltmak için sayılan saatlere dokunmayacaktır. Bu gibi durumlarda daha karmaşık bir çözüm uygulanmalıdır. Bulunan tüm geçişler üzerinde yineleme yapılabilir ve sonuncusu ile akım karşılaştırılabilir ve DST true-> false ile bir olup olmadığı kontrol edilebilir.
strftime()ve farkı 3600'e bölmek olurdu , ama bu her zaman işe yarayacak mı? Lanet olsun, Gün Işığından Yararlanma Zamanı!