คำนวณจำนวนชั่วโมงระหว่างวันที่ 2 ใน PHP


108

ฉันจะคำนวณความแตกต่างระหว่างสองวันที่เป็นชั่วโมงได้อย่างไร

ตัวอย่างเช่น:

day1=2006-04-12 12:30:00
day2=2006-04-14 11:30:00

ในกรณีนี้ผลลัพธ์ควรเป็น 47 ชั่วโมง


1
คำตอบเริ่มต้นของฉันจะเปลี่ยนทั้งสองค่าเป็นการประทับเวลาโดยใช้strftime()และแบ่งความแตกต่างด้วย 3600 แต่จะได้ผลหรือไม่ ประณามคุณเวลาออมแสง!
Pekka

@Pekka: ไม่ได้ผลเสมอไปฉันเดา ... ดูคำตอบของฉัน ที่นั่นฉันได้โพสต์วิธีแก้ปัญหาโดยพิจารณาเขตเวลาปีอธิกสุรทินวินาทีอธิกสุรทินและ dst :)
Fidi

@Pekka ถ้าคุณใช้strtotime()มันจะใช้ได้เสมอตราบใดที่คุณใช้เขตเวลาเริ่มต้นหรือระบุเขตเวลาชดเชยอย่างชัดเจน ไม่มีเหตุผลที่จะด่าจขกท.
Walter Tross

คำตอบ:


210

ใหม่ PHP-รุ่นให้เรียนใหม่บางอย่างที่เรียกว่าDateTime, DateInterval, และDateTimeZone DatePeriodสิ่งที่น่าสนใจเกี่ยวกับคลาสนี้คือการพิจารณาเขตเวลาที่แตกต่างกันปีอธิกสุรทินวินาทีอธิกสุรทิน ฯลฯ และยิ่งไปกว่านั้นมันใช้งานง่ายมาก นี่คือสิ่งที่คุณต้องการด้วยความช่วยเหลือของวัตถุนี้:

// Create two new DateTime-objects...
$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');

// The diff-methods returns a new DateInterval-object...
$diff = $date2->diff($date1);

// Call the format method on the DateInterval-object
echo $diff->format('%a Day and %h hours');

DateInterval วัตถุซึ่งจะถูกส่งกลับนอกจากนี้ยังมีวิธีการอื่น ๆ formatกว่า หากคุณต้องการผลลัพธ์ในไม่กี่ชั่วโมงเท่านั้นคุณสามารถทำได้ดังนี้:

$date1 = new DateTime('2006-04-12T12:30:00');
$date2 = new DateTime('2006-04-14T11:30:00');

$diff = $date2->diff($date1);

$hours = $diff->h;
$hours = $hours + ($diff->days*24);

echo $hours;

และนี่คือลิงค์สำหรับเอกสาร:

ชั้นเรียนทั้งหมดเหล่านี้ยังมีขั้นตอน / วิธีการทำงานในการดำเนินการกับวันที่ ดังนั้นลองดูภาพรวม: http://php.net/manual/book.datetime.php


+1 ดีมาก! สิ่งนี้ดูมั่นคงและเป็นภาพรวมที่ดี สิ่งสำคัญคือต้องทราบว่าการคำนวณอาจแตกต่างกันไปตามเขตเวลาเนื่องจากกฎ DST ที่แตกต่างกันดังนั้นจึงควรกำหนดโซนเสมอและไม่ต้องพึ่งพาการตั้งค่าเซิร์ฟเวอร์
Pekka

ใช่. ด้วยวัตถุนี้คุณสามารถคำนวณระหว่างวันที่ในเขตเวลาต่างๆได้ $date1 = new DateTime('2006-04-12T12:30:00 Europe/Berlin');และ$date2 = new DateTime('2006-04-14T11:30:00 America/New_York');
Fidi

4
หากมีคนพบปัญหาเดียวกันกับที่ฉันเพิ่งทำโดยที่$diff->dเท่ากับ 0 (เพราะฉันพยายามคำนวณชั่วโมงระหว่างวันที่สองวันที่ห่างกัน 2 เดือนอย่างแน่นอน): การวิ่งvar_dump($diff)แสดงพารามิเตอร์อื่นให้ฉัน: ["days"]=>int(61)ดังนั้นฉันจึงใช้$hours = $diff->days * 24;และมันก็มา ใกล้เคียงกับ "ค่าเฉลี่ย" ที่ 1440 ชั่วโมงใน 2 เดือน 30 วันดังนั้นจึงดูดีกว่าผลของ 0 มาก (เดาว่าเวอร์ชัน PHP ของฉันเก่าไปหน่อย ... )
semmelbroesel

2
ฉันหมายความว่าในหลาย ๆ ส่วนของโลกในหนึ่งปีมีหนึ่งวัน 23 ชั่วโมงและหนึ่งวัน 25 ชั่วโมง
Walter Tross

4
@Amal Murali ดังนั้นคุณจึงตัดสินใจที่จะให้รางวัลโบนัสสำหรับคำตอบนี้ซึ่งผิด? คุณได้ลองคำนวณจำนวนชั่วโมงระหว่างเที่ยงของวันแรกของเดือนมกราคมถึงเที่ยงวันของเดือนมิถุนายนโดยใช้คำตอบนี้ในเขตเวลาใด ๆ ที่มี DST (เวลาออมแสง) หรือไม่ คุณจะได้ผลลัพธ์ที่เป็นคู่ในขณะที่ผลลัพธ์ที่แท้จริงเป็นเลขคี่
Walter Tross

79
$t1 = strtotime( '2006-04-14 11:30:00' );
$t2 = strtotime( '2006-04-12 12:30:00' );
$diff = $t1 - $t2;
$hours = $diff / ( 60 * 60 );

5
ทำไมไม่$diff / 3600?
Alex G

4
@AlexG มันเป็นแค่สไตล์ ผลลัพธ์เดียวกัน แต่โปรแกรมเมอร์มักจะใช้การคูณเมื่อพูดถึงเวลา
ผู้ใช้

ฉันแนะนำให้คุณชอบ: round (($ t1 - $ 22) / 3600); ใช้รอบเพื่อให้ได้ชั่วโมงที่ถูกต้อง
ชีฟซิงห์

20

เพื่อให้วิธีการอื่นDatePeriodเมื่อใช้UTCหรือเวลา GMTเขตเวลา

นับชั่วโมงhttps://3v4l.org/Mu3HD

$start = new \DateTime('2006-04-12T12:30:00');
$end = new \DateTime('2006-04-14T11:30:00');

//determine what interval should be used - can change to weeks, months, etc
$interval = new \DateInterval('PT1H');

//create periods every hour between the two dates
$periods = new \DatePeriod($start, $interval, $end);

//count the number of objects within the periods
$hours = iterator_count($periods);
echo $hours . ' hours'; 

//difference between Unix Epoch
$diff = $end->getTimestamp() - $start->getTimestamp();
$hours = $diff / ( 60 * 60 );
echo $hours . ' hours (60 * 60)';

//difference between days
$diff = $end->diff($start);
$hours = $diff->h + ($diff->days * 24);
echo $hours . ' hours (days * 24)';

ผลลัพธ์

47 hours (iterator_count)
47 hours (60 * 60)
47 hours (days * 24)

นับชั่วโมงด้วย Daylight Savings https://3v4l.org/QBQUB

โปรดทราบว่าDatePeriodยกเว้นหนึ่งชั่วโมงสำหรับ DST แต่จะไม่เพิ่มอีกชั่วโมงเมื่อ DST สิ้นสุดลง ดังนั้นการใช้งานจึงขึ้นอยู่กับผลลัพธ์และช่วงวันที่ที่คุณต้องการ

ดูรายงานข้อบกพร่องปัจจุบัน

//set timezone to UTC to disregard daylight savings
date_default_timezone_set('America/New_York');

$interval = new \DateInterval('PT1H');

//DST starts Apr. 2nd 02:00 and moves to 03:00
$start = new \DateTime('2006-04-01T12:00:00');  
$end = new \DateTime('2006-04-02T12:00:00');

$periods = new \DatePeriod($start, $interval, $end);
$hours = iterator_count($periods);
echo $hours . ' hours';

//DST ends Oct. 29th 02:00 and moves to 01:00
$start = new \DateTime('2006-10-28T12:00:00');
$end = new \DateTime('2006-10-29T12:00:00'); 

$periods = new \DatePeriod($start, $interval, $end);
$hours = iterator_count($periods);
echo $hours . ' hours';

ผลลัพธ์

#2006-04-01 12:00 EST to 2006-04-02 12:00 EDT
23 hours (iterator_count)
//23 hours (60 * 60)
//24 hours (days * 24)

#2006-10-28 12:00 EDT to 2006-10-29 12:00 EST
24 hours (iterator_count)
//25 hours (60 * 60)
//24 hours (days * 24)

#2006-01-01 12:00 EST to 2007-01-01 12:00 EST
8759 hours (iterator_count)
//8760 hours (60 * 60)
//8760 hours (days * 24)

//------

#2006-04-01 12:00 UTC to 2006-04-02 12:00 UTC
24 hours (iterator_count)
//24 hours (60 * 60)
//24 hours (days * 24)

#2006-10-28 12:00 UTC to 2006-10-29 12:00 UTC
24 hours (iterator_count)
//24 hours (60 * 60)
//24 hours (days * 24)

#2006-01-01 12:00 UTC to 2007-01-01 12:00 UTC
8760 hours (iterator_count)
//8760 hours (60 * 60)
//8760 hours (days * 24)

1
สำหรับใครที่สับสนเหมือนฉันเห็นพารามิเตอร์ตัวสร้าง DateInterval รูปแบบคือISO 8601 Duration
TheKarateKid

ข้อสังเกตอีกประการหนึ่งคือDateIntervalไม่ยอมรับค่าเศษส่วนตามข้อกำหนด ISO 8601 ดังนั้นจึงP1.2Yไม่ใช่ระยะเวลาที่ถูกต้องใน PHP
fyrye

หมายเหตุ: iterator_count จะให้ผลลัพธ์ที่เป็นบวกเท่านั้น ถ้าวันแรกมากกว่าวันที่สองผลลัพธ์ที่แตกต่างจะเป็น 0
SubjectDelta

1
@SubjectDelta ปัญหาไม่เกี่ยวข้องiterator_countเกิดจากDatePeriodไม่สามารถสร้างวันที่เมื่อวันที่เริ่มต้นอยู่ในอนาคตนับจากวันที่สิ้นสุด ดู: 3v4l.org/Ypsp1 ในการใช้วันที่ติดลบคุณต้องระบุช่วงเวลาเชิงลบDateInterval::createFromDateString('-1 hour');โดยมีวันที่เริ่มต้นในอดีตจากวันที่สิ้นสุด
fyrye

1
@SubjectDelta นี่เป็นความแตกต่างเล็กน้อยของDatePeriodเนื่องจากโดยค่าเริ่มต้นจะรวมวันที่เริ่มต้นระหว่างช่วงเวลาที่ระบุเว้นแต่จะน้อยกว่าหรือเท่ากับวันที่เริ่มต้น คุณกำลังบอกให้ php สร้างช่วงเวลา 1 ชั่วโมงระหว่างวันที่สองวันภายใน 1 วินาที DateTime::setTime(date->format('H'), 0)คุณจะต้องลบนาทีและวินาทีจากวัตถุวันของคุณเป็นพวกเขาไม่ได้มีความเกี่ยวข้องในการคำนวณโดยใช้ 3v4l.org/K7ussวิธีนี้หากคุณอยู่เกินช่วง 1 วินาทีวันที่อื่นจะไม่ถูกสร้างขึ้น
fyrye

18

คำตอบของคุณคือ:

round((strtotime($day2) - strtotime($day1))/(60*60))


5
เกิดอะไรขึ้นถ้าระหว่าง 2 ชั่วโมง 30 นาที? คำตอบของคุณจะส่งผลใน 3 ชั่วโมง ฉันคิดว่ามันจะดีกว่าถ้าใช้พื้นเพื่อให้ได้ผล 2 ชั่วโมง ขึ้นอยู่กับสถานการณ์จริงๆ
Kapitein Witbaard

15

วิธีที่ง่ายที่สุดในการรับจำนวนชั่วโมงที่ถูกต้องระหว่างวันที่สองวัน (เวลาวันที่) แม้กระทั่งการเปลี่ยนแปลงเวลาออมแสงคือการใช้ความแตกต่างในการประทับเวลา Unix การประทับเวลา Unix เป็นวินาทีที่ผ่านไปนับตั้งแต่ 1970-01-01T00: 00: 00 UTC โดยไม่สนใจวินาทีอธิกสุรทิน (ใช้ได้เพราะคุณอาจไม่ต้องการความแม่นยำนี้และเนื่องจากการใช้เวลาอธิกวินาทีค่อนข้างยาก)

วิธีที่ยืดหยุ่นที่สุดในการแปลงสตริงวันที่และเวลาที่มีข้อมูลเขตเวลาที่เป็นทางเลือกให้เป็นการประทับเวลา Unix คือการสร้างอ็อบเจ็กต์DateTime (ทางเลือกที่มีDateTimeZoneเป็นอาร์กิวเมนต์ที่สองในตัวสร้าง) จากนั้นเรียกใช้เมธอดgetTimestamp

$str1 = '2006-04-12 12:30:00'; 
$str2 = '2006-04-14 11:30:00';
$tz1 = new DateTimeZone('Pacific/Apia');
$tz2 = $tz1;
$d1 = new DateTime($str1, $tz1); // tz is optional,
$d2 = new DateTime($str2, $tz2); // and ignored if str contains tz offset
$delta_h = ($d2->getTimestamp() - $d1->getTimestamp()) / 3600;
if ($rounded_result) {
   $delta_h = round ($delta_h);
} else if ($truncated_result) {
   $delta_h = intval($delta_h);
}
echo "Δh: $delta_h\n";

1
จากความคิดเห็นในคู่มือปรากฏว่าสำหรับความเข้ากันได้กับวันก่อนยุคformat("U")นิยมใช้getTimestamp()
อาทิตย์

1
@Arth ฉันไม่รู้ว่าเมื่อไหร่จะเป็นเช่นนั้น แต่ใน PHP 5.5.9 ของฉันมันไม่จริงอีกต่อไป getTimestamp()ตอนนี้ส่งกลับค่าเดียวกับformat("U"). แม้ว่าอดีตจะเป็นจำนวนเต็มในขณะที่ตัวหลังเป็นสตริง (มีประสิทธิภาพน้อยกว่าที่นี่)
Walter Tross

เยี่ยมไปเลยบางทีมันอาจจะเป็นจริงในเวอร์ชันก่อนหน้านี้ก็ได้ .. จำนวนเต็มจะสะอาดกว่าดังนั้นฉันต้องการgetTimestamp()ถ้าจะให้แน่ใจ
อาทิตย์

4
//Calculate number of hours between pass and now
$dayinpass = "2013-06-23 05:09:12";
$today = time();
$dayinpass= strtotime($dayinpass);
echo round(abs($today-$dayinpass)/60/60);



2

น่าเสียดายที่วิธีการแก้ปัญหาของ FaileN ไม่ทำงานตามที่กำหนดโดย Walter Tross .. วันอาจไม่ใช่ 24 ชั่วโมง!

ฉันชอบใช้ PHP Objects ถ้าเป็นไปได้และเพื่อความยืดหยุ่นที่มากขึ้นฉันได้พบกับฟังก์ชันต่อไปนี้:

/**
 * @param DateTimeInterface $a
 * @param DateTimeInterface $b
 * @param bool              $absolute Should the interval be forced to be positive?
 * @param string            $cap The greatest time unit to allow
 *
 * @return DateInterval The difference as a time only interval
 */
function time_diff(DateTimeInterface $a, DateTimeInterface $b, $absolute=false, $cap='H'){

  // Get unix timestamps, note getTimeStamp() is limited
  $b_raw = intval($b->format("U"));
  $a_raw = intval($a->format("U"));

  // Initial Interval properties
  $h = 0;
  $m = 0;
  $invert = 0;

  // Is interval negative?
  if(!$absolute && $b_raw<$a_raw){
    $invert = 1;
  }

  // Working diff, reduced as larger time units are calculated
  $working = abs($b_raw-$a_raw);

  // If capped at hours, calc and remove hours, cap at minutes
  if($cap == 'H') {
    $h = intval($working/3600);
    $working -= $h * 3600;
    $cap = 'M';
  }

  // If capped at minutes, calc and remove minutes
  if($cap == 'M') {
    $m = intval($working/60);
    $working -= $m * 60;
  }

  // Seconds remain
  $s = $working;

  // Build interval and invert if necessary
  $interval = new DateInterval('PT'.$h.'H'.$m.'M'.$s.'S');
  $interval->invert=$invert;

  return $interval;
}

เช่นนี้date_diff()จะสร้าง a DateTimeIntervalแต่มีหน่วยสูงสุดเป็นชั่วโมงแทนที่จะเป็นปี .. สามารถจัดรูปแบบได้ตามปกติ

$interval = time_diff($date_a, $date_b);
echo $interval->format('%r%H'); // For hours (with sign)

NBฉันได้ใช้format('U')แทนgetTimestamp()เพราะความคิดเห็นในที่คู่มือ โปรดทราบว่า 64 บิตเป็นสิ่งจำเป็นสำหรับวันหลังยุคและก่อนยุคลบ!


0

ฟังก์ชั่นนี้จะช่วยให้คุณสามารถคำนวณปีแน่นอนและเดือนระหว่างวันที่สองวันที่กำหนดและ$doj1 $dojส่งกลับตัวอย่าง 4.3 หมายถึง 4 ปี 3 เดือน

<?php
    function cal_exp($doj1)
    {
        $doj1=strtotime($doj1);
        $doj=date("m/d/Y",$doj1); //till date or any given date

        $now=date("m/d/Y");
        //$b=strtotime($b1);
        //echo $c=$b1-$a2;
        //echo date("Y-m-d H:i:s",$c);
        $year=date("Y");
        //$chk_leap=is_leapyear($year);

        //$year_diff=365.25;

        $x=explode("/",$doj);
        $y1=explode("/",$now);

        $yy=$x[2];
        $mm=$x[0];
        $dd=$x[1];

        $yy1=$y1[2];
        $mm1=$y1[0];
        $dd1=$y1[1];
        $mn=0;
        $mn1=0;
        $ye=0;
        if($mm1>$mm)
        {
            $mn=$mm1-$mm;
            if($dd1<$dd)
            {
                $mn=$mn-1;
            }
            $ye=$yy1-$yy;
        }
        else if($mm1<$mm)
        {
            $mn=12-$mm;
            //$mn=$mn;

            if($mm!=1)
            {
                $mn1=$mm1-1;
            }

            $mn+=$mn1;
            if($dd1>$dd)
            {
                $mn+=1;
            }

            $yy=$yy+1;
            $ye=$yy1-$yy;
        }
        else
        {
            $ye=$yy1-$yy;
            $ye=$ye-1;

            $mn=12-1;

            if($dd1>$dd)
            {
                $ye+=1;
                $mn=0;
            }
        }

        $to=$ye." year and ".$mn." months";
        return $ye.".".$mn;

        /*return daysDiff($x[2],$x[0],$x[1]);
         $days=dateDiff("/",$now,$doj)/$year_diff;
        $days_exp=explode(".",$days);
        return $years_exp=$days; //number of years exp*/
    }
?>

การแก้ไขที่แนะนำน้อยเกินไป แต่<phpจำเป็นต้องเปลี่ยนเป็น<?phpหรืออนุมัติการแก้ไขที่แนะนำซึ่งจะลบข้อบกพร่องทั้งหมดรวมกัน
anishsane

0

กำลังทำงานในโครงการของฉัน ฉันคิดว่านี่จะเป็นประโยชน์สำหรับคุณ

หากวันที่ผ่านมาแล้วจะกลับด้าน 1
หากวันที่อยู่ในอนาคตการกลับด้านจะเป็น 0

$defaultDate = date('Y-m-d');   
$datetime1   = new DateTime('2013-03-10');  
$datetime2   = new DateTime($defaultDate);  
$interval    = $datetime1->diff($datetime2);  
$days        = $interval->format('%a');
$invert      = $interval->invert;

0

ในการส่งการประทับเวลายูนิกซ์ให้ใช้สัญกรณ์นี้

$now        = time();
$now        = new DateTime("@$now");

1
หมายเหตุเขตเวลาจะถูกส่งผ่านและส่งออก+0:00เมื่อใช้@ในตัวสร้าง DateTime ในขณะที่ใช้DateTime::modify()วิธีนี้จะส่งการประทับเวลาเป็น+0:00และส่งออกเขตเวลาปัจจุบัน หรือใช้$date = new DateTime(); $date->setTimestamp($unix_timestamp);ดู: 3v4l.org/BoAWI
fyrye

0

คาร์บอนอาจเป็นวิธีที่ดี

จากเว็บไซต์ของพวกเขา:

ส่วนขยาย PHP API ง่ายๆสำหรับ DateTime http://carbon.nesbot.com/

ตัวอย่าง:

use Carbon\Carbon;

//...

$day1 = Carbon::createFromFormat('Y-m-d H:i:s', '2006-04-12 12:30:00');
$day2 = Carbon::createFromFormat('Y-m-d H:i:s', '2006-04-14 11:30:00');

echo $day1->diffInHours($day2); // 47

//...

คาร์บอนขยายชั้น DateTime diff()วิธีการสืบทอดรวมทั้ง มันจะเพิ่มน้ำตาลที่ดีเช่นdiffInHours, diffInMintutes, diffInSecondsฯลฯ


0

ขั้นแรกคุณควรสร้างวัตถุช่วงเวลาจากช่วงวันที่ โดยใช้ถ้อยคำในประโยคนี้เพียงอย่างเดียวเราสามารถระบุนามธรรมพื้นฐานที่จำเป็นได้อย่างง่ายดาย มีช่วงเวลาเป็นแนวคิดและอีกสองสามวิธีในการนำไปใช้รวมถึงวิธีที่กล่าวไปแล้ว - จากช่วงวันที่ ดังนั้นช่วงเวลาจึงมีลักษณะดังนี้:

$interval =
    new FromRange(
        new FromISO8601('2017-02-14T14:27:39+00:00'),
        new FromISO8601('2017-03-14T14:27:39+00:00')
    );

FromISO8601มีความหมายเหมือนกัน: เป็นวัตถุ datetime ที่สร้างขึ้นfrom iso8601-formatted stringดังนั้นชื่อ

เมื่อคุณมีช่วงเวลาคุณสามารถจัดรูปแบบได้ตามต้องการ หากคุณต้องการจำนวนชั่วโมงเต็มคุณสามารถมีได้

(new TotalFullHours($interval))->value();

หากคุณต้องการชั่วโมงทั้งหมดที่ไม่สิ้นสุดให้ไปที่นี่:

(new TotalCeiledHours($interval))->value();

สำหรับข้อมูลเพิ่มเติมเกี่ยวกับแนวทางนี้และตัวอย่างบางส่วนโปรดดูรายการนี้


0

นอกจากคำตอบที่เป็นประโยชน์มากของ @ fyrye แล้วนี่เป็นวิธีแก้ปัญหาที่ถูกต้องสำหรับข้อบกพร่องที่กล่าวถึง (อันนี้ ) DatePeriod จะแทนที่หนึ่งชั่วโมงเมื่อเข้าสู่ฤดูร้อน แต่จะไม่เพิ่มหนึ่งชั่วโมงเมื่อออกจากฤดูร้อน (ดังนั้นเดือนมีนาคมของยุโรป / เบอร์ลินจึงมี ถูกต้อง 743 ชั่วโมง แต่ตุลาคมมี 744 แทนที่จะเป็น 745 ชั่วโมง):

การนับชั่วโมงของเดือน (หรือช่วงเวลาใด ๆ ) โดยพิจารณาจากการเปลี่ยน DST ทั้งสองทิศทาง

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

ป.ล. หากคุณตรวจสอบช่วงเวลา (นานกว่า) ซึ่งนำไปสู่การเปลี่ยนมากกว่าสองครั้งวิธีแก้ปัญหาของฉันจะไม่แตะจำนวนชั่วโมงที่นับเพื่อลดโอกาสของผลข้างเคียงที่น่าขบขัน ในกรณีเช่นนี้จะต้องดำเนินการแก้ไขปัญหาที่ซับซ้อนมากขึ้น เราสามารถวนซ้ำการเปลี่ยนแปลงที่พบทั้งหมดและเปรียบเทียบปัจจุบันกับช่วงสุดท้ายและตรวจสอบว่าเป็นหนึ่งเดียวกับ DST จริง -> เท็จหรือไม่


โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.