我有一个类似这样的Unix时间戳:
$timestamp=1330581600
如何获取给定时间戳所在日期的开始时间和结束时间?
e.g.
$beginOfDay = Start of Timestamp's Day
$endOfDay = End of Timestamp's Day
我尝试过这个:
$endOfDay = $timestamp + (60 * 60 * 23);
但我认为这不会起作用,因为时间戳本身并不是一天的确切开始。
我有一个类似这样的Unix时间戳:
$timestamp=1330581600
如何获取给定时间戳所在日期的开始时间和结束时间?
e.g.
$beginOfDay = Start of Timestamp's Day
$endOfDay = End of Timestamp's Day
我尝试过这个:
$endOfDay = $timestamp + (60 * 60 * 23);
但我认为这不会起作用,因为时间戳本身并不是一天的确切开始。
strtotime函数可以快速削减日期时间中的小时/分钟/秒
$beginOfDay = strtotime("today", $timestamp);
$endOfDay = strtotime("tomorrow", $beginOfDay) - 1;
DateTime也可以使用,但需要进行一些额外的步骤才能从长时间戳中获取日期时间信息。
$dtNow = new DateTime();
// Set a non-default timezone if needed
$dtNow->setTimezone(new DateTimeZone('Pacific/Chatham'));
$dtNow->setTimestamp($timestamp);
$beginOfDay = clone $dtNow;
$beginOfDay->modify('today');
$endOfDay = clone $beginOfDay;
$endOfDay->modify('tomorrow');
// adjust from the start of next day to the end of the day,
// per original question
// Decremented the second as a long timestamp rather than the
// DateTime object, due to oddities around modifying
// into skipped hours of day-lights-saving.
$endOfDateTimestamp = $endOfDay->getTimestamp();
$endOfDay->setTimestamp($endOfDateTimestamp - 1);
var_dump(
array(
'time ' => $dtNow->format('Y-m-d H:i:s e'),
'start' => $beginOfDay->format('Y-m-d H:i:s e'),
'end ' => $endOfDay->format('Y-m-d H:i:s e'),
)
);
随着PHP7中增加了扩展时间,如果使用$now <= $end
进行检查可能会错过一秒钟。使用$now < $nextStart
进行检查将避免这种间隙,并解决PHP时间处理中减去秒和夏令时的奇怪问题。
strtotime('today', $timestamp)
。 - Semra$endOfDay->modify('tomorrow -1 second');
同样有效。 - CGodo$beginOfDay = DateTime::createFromFormat('Y-m-d H:i:s', (new DateTime())->setTimestamp($timestamp)->format('Y-m-d 00:00:00'))->getTimestamp();
$endOfDay = DateTime::createFromFormat('Y-m-d H:i:s', (new DateTime())->setTimestamp($timestamp)->format('Y-m-d 23:59:59'))->getTimestamp();
首先创建一个DateTime对象并将时间戳设置为所需的时间戳。然后将对象格式化为一个字符串,并将小时/分钟/秒设置为当天的开始或结束。最后,从此字符串创建一个新的DateTime对象并检索时间戳。
$dateTimeObject = new DateTime();
$dateTimeObject->setTimestamp($timestamp);
$beginOfDayString = $dateTimeObject->format('Y-m-d 00:00:00');
$beginOfDayObject = DateTime::createFromFormat('Y-m-d H:i:s', $beginOfDayString);
$beginOfDay = $beginOfDayObject->getTimestamp();
我们可以使用这个较长的版本以另一种方式得到一天的结束:
$endOfDayObject = clone $beginOfDayOject(); // Cloning because add() and sub() modify the object
$endOfDayObject->add(new DateInterval('P1D'))->sub(new DateInterval('PT1S'));
$endOfDay = $endOfDayOject->getTimestamp();
也可以通过在格式中添加时间戳指示符(例如O
),并在创建DateTime对象后指定时间戳来设置时区:
$beginOfDay = DateTime::createFromFormat('Y-m-d H:i:s O', (new DateTime())->setTimezone(new DateTimeZone('America/Los_Angeles'))->setTimestamp($timestamp)->format('Y-m-d 00:00:00 O'))->getTimestamp();
我们可以通过更改指定的格式来获取其他信息,例如月份的开始/结束或小时的开始/结束。对于月份: 'Y-m-01 00:00:00'
和 'Y-m-t 23:59:59'
。 对于小时: 'Y-m-d H:00:00'
和 'Y-m-d H:59:59'
结合add()/sub()和DateInterval对象使用各种格式,我们可以获得任何期间的开始或结束时间,尽管需要注意正确处理闰年。
来自PHP文档:
date()
和 mktime()
的组合:list($y,$m,$d) = explode('-', date('Y-m-d', $ts));
$start = mktime(0,0,0,$m,$d,$y);
$end = mktime(0,0,0,$m,$d+1,$y);
mktime()
函数在处理日期时会自动调整月份/年份,当给定的日期不在指定的月份内时(如1月32日将被调整为2月1日等)。
$start_of_day = time() - 86400 + (time() % 86400);
$end_of_day = $start_of_day + 86400;
time()
时,它们可能是不同的秒数。 - Chris Harrison// IMPORTANT
行之后:$dtNow = new DateTime();
// Set a non-default timezone if needed
$dtNow->setTimezone(new DateTimeZone('America/Havana'));
$dtNow->setTimestamp($timestamp);
$beginOfDay = clone $dtNow;
// Go to midnight. ->modify('midnight') does not do this for some reason
$beginOfDay->modify('today');
// now get the beginning of the next day
$endOfDay = clone $beginOfDay;
$endOfDay->modify('tomorrow');
// IMPORTANT
// get the timestamp
$ts = $endOfDay->getTimestamp();
// subtract one from that timestamp
$tsEndOfDay = $ts - 1;
// we now have the timestamp at the end of the day. we can now use that timestamp
// to set our end of day DateTime
$endOfDay->setTimestamp($tsEndOfDay);
->modify('1 second ago');
。虽然使用modify
的答案理应可行,但由于php中一个非常特定的错误而无法使用。这个错误出现在夏令时在午夜更改时区,且在将时钟向前调整的那一天。以下是一个示例代码,您可以使用它来验证该错误。
错误示例代码:
// a time zone, Cuba, that changes their clocks forward exactly at midnight. on
// the day before they make that change. there are other time zones which do this
$timezone = 'America/Santiago';
$dateString = "2020-09-05";
echo 'the start of the day:<br>';
$dtStartOfDay = clone $dtToday;
$dtStartOfDay->modify('today');
echo $dtStartOfDay->format('Y-m-d H:i:s');
echo ', '.$dtStartOfDay->getTimestamp();
echo '<br><br>the start of the *next* day:<br>';
$dtEndOfDay = clone $dtToday;
$dtEndOfDay->modify('tomorrow');
echo $dtEndOfDay->format('Y-m-d H:i:s');
echo ', '.$dtEndOfDay->getTimestamp();
echo '<br><br>the end of the day, this is incorrect. notice that with ->modify("-1 second") the second does not decrement the timestamp by 1:<br>';
$dtEndOfDayMinusOne = clone $dtEndOfDay;
$dtEndOfDayMinusOne->modify('1 second ago');
echo $dtEndOfDayMinusOne->format('Y-m-d H:i:s');
echo ', '.$dtEndOfDayMinusOne->getTimestamp();
echo '<br><br>the end of the day, this is correct:<br>';
$dtx = clone $dtEndOfDay;
$tsx = $dtx->getTimestamp() - 1;
$dty = clone $dtEndOfDay;
$dty->setTimestamp($tsx);
echo $dty->format('Y-m-d H:i:s');
echo ', '.$tsx;
代码漏洞示例输出
the start of the day:
2020-03-26 00:00:00, 1585173600
the start of the *next* day:
2020-03-27 01:00:00, 1585260000
the end of the day, this is incorrect. notice that with ->modify("1 second ago") the
second does not decrement the timestamp by 1:
2020-03-27 01:59:59, 1585263599
the end of the day, this is correct:
2020-03-26 23:59:59, 1585259999
$stamp = mktime(0, 0, 0);
echo date('m-d-Y H:i:s',$stamp);
$start_of_day = floor (time() / 86400) * 86400;
$end_of_day = ceil (time() / 86400) * 86400;
$start_of_day = floor (time() / 86400) * 86400;
$end_of_day = $start_of_day + 86400;
对于将来有这个问题的任何人:
任何日期代码
<?php
$date = "2015-04-12 09:20:00";
$midnight = strtotime("midnight", strtotime($date));
$now = strtotime($date);
$diff = $now - $midnight;
echo $diff;
?>
现今的代码
<?php
$midnight = strtotime("midnight");
$now = date('U');
$diff = $now - $midnight;
echo $diff;
?>
$date = (new \DateTime())->setTimestamp(1330581600);
echo $date->modify('today')->format('Y-m-d H:i:s'); // 2012-02-29 00:00:00
echo PHP_EOL;
echo $date->modify('tomorrow - 1 second')->format('Y-m-d H:i:s'); // 2012-02-29 23:59:59
$beginOfDay = (new DateTime('today', new DateTimeZone('Asia/Tehran')))->getTimestamp();
$endOfDay = $beginOfDay + 86399;
你可以通过替换 "Asia/Tehran" 来设置时区。一天是 86400 秒,不要问我为什么是 86399,它只是我脑海里的一个耳语,所以我甚至不想去考虑它的真实性。