유닉스 타임 스탬프가 주어지면 그날의 시작과 끝을 얻는 방법은 무엇입니까?


80

다음과 같은 Unix 타임 스탬프가 있습니다.

$timestamp=1330581600

해당 타임 스탬프에 대한 하루의 시작과 끝을 어떻게 가져 옵니까?

e.g.
$beginOfDay = Start of Timestamp's Day
$endOfDay = End of Timestamp's Day

나는 이것을 시도했다 :

$endOfDay = $timestamp + (60 * 60 * 23);

하지만 타임 스탬프 자체가 하루의 정확한 시작이 아니기 때문에 작동하지 않을 것이라고 생각합니다.


GMT라면 아마도 : $ boundary = floor / ceil ($ timestamp / (60 * 60 * 24)) * (60 * 60 * 24);
hakre

예상 출력이 정수인 타임 스탬프 인 경우 간단한 한 줄이 있습니다. $ beginOfDay = mktime (0, 0, 0, date ( 'n'), date ( 'j')-1); $ endOfDay = mktime (0, 0, 0, date ( 'n'), date ( 'j'));
jarederaj

답변:


177

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이것으로 검사를 사용하면 1 초를 놓칠 가능성 이 있습니다. $now < $nextStart검사를 사용하면 PHP의 시간 처리에서 초를 빼고 일광 절약을 할 수있는 이상한 점 외에도 그 차이를 피할 수 있습니다.


2
마지막에 왜 마이너스 1 초입니까?
Kurt Zhong

1
나는 원래 질문을 다음 날의 첫 번째 초가 아니라 하루의 마지막 초를 얻는 것으로 읽었습니다. '내일'은 하루의 첫 번째 초를 제공하므로 '-1'은 하루의 첫 번째 초 전에 두 번째를 가져옵니다.
rrehbein

5
'today'는 또한 하루의 시작을 반환합니다.strtotime('today', $timestamp)
Semra

1
윤초 문제가 발생하는 경향이있는 것
Brad Kent

4
$endOfDay->modify('tomorrow -1 second');또한 작동합니다.
CGodo

11

DateTime 만

$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();

DateTime의 유연성

지정된 두 번째 형식을 변경하여 월의 시작 / 종료 또는 시간의 시작 / 종료와 같은 다른 정보를 얻을 수도 있습니다. 월 : '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 문서에서 :


2
당신이 만든 것은 간결하고 읽기 쉽습니다. 유감스럽게도 윤초에 실패합니다. 어떤 날은 23:59:58에 끝나고 다른 날은 23:59:60에 끝납니다. 특히 이론적으로 1 초 전에 종료 될 수있는 날짜의 23:59:59와 같이 존재하지 않는 datetime에 대한 날짜를 만들려고하면 문제가 발생합니다. PHP의 \ DateTime :: modify 메서드를 사용하는 허용 된 대답은 이것을 피할 것입니다. PHP의 내장 lib는 윤초를 포함하여 날짜와 시간을 둘러싼 모든 이상한 점을 충분히 감안할 수있을만큼 똑똑합니다.
Elimn

@Elimm, 나는 윤일 때문에 어떤 날이 1 초 전후로 끝나는 것을 알지 못했습니다. 나는 도약이 윤년에 하루를 추가하고 다른 것은 영향을 미치지 않는다고 생각했습니다. 이것이 어떻게 실패하는지에 대한 코드에서 몇 가지 예를 들어 줄 수 있습니까 (또는 1 초 이상 또는 1 초 미만의 하루를 공유 할 수 있습니까)? 또한 이것에 대해 더 자세히 설명하는 기사가 있습니까? 지적 해 주셔서 감사합니다 modify. 나는 그것에 대해 전에 몰랐습니다.
Robert Hickman

물론입니다. 이러한 도약라고 초를 뛰어없는 또는 . 그들은 지구의 자전이 일정한 속도가 아닌 것을 설명합니다. 2016 년 6 월 30 일이 우리의 마지막 윤초라고 생각합니다. 위키 백과 페이지 견실 한 세부 사항에에서 다이빙.
Elimn

7

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 일 등).


4

시간을 현재 데이터로 변환 한 다음 strtotime 함수를 사용하여 하루의 시작을 찾고 24 시간을 추가하여 하루의 끝을 찾을 수 있습니다.

나머지 연산자 (%)를 사용하여 가장 가까운 날짜를 찾을 수도 있습니다. 예를 들면 :

$start_of_day = time() - 86400 + (time() % 86400);
$end_of_day = $start_of_day + 86400;

7
모든 일 86,400초이 늘 일 때문에 예상대로, 긴

오, 그래 @Cal, 나는 그 생각을하지 않았다
카메론

2
time()두 번 전화하면 초가 다를 수 있습니다.
Chris Harrison

@ChrisHarrison $ now = 시간 (); $ start_of_day = $ now-86400 + ($ now % 86400);
Kareem

4

안타깝게도 매우 구체적인 시나리오에서 발생하는 PHP 버그로 인해 허용되는 답변이 중단됩니다. 이러한 시나리오에 대해 설명하지만 먼저 DateTime을 사용하여 답변합니다. 이것과 허용되는 대답의 유일한 차이점은 다음 // 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

3

오늘 시작 날짜 타임 스탬프입니다. 단순한

$stamp = mktime(0, 0, 0);
echo date('m-d-Y H:i:s',$stamp);

1
이것은 일광 절약 시간이 자정에 정확히 변경이 일에 예기치 않은 동작이 발생할 수 있습니다
KayakinKoder

0

앞으로이 질문이있는 모든 사람을 위해 :

모든 요일 코드

<?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;
?>

0
$start_of_day = floor (time() / 86400) * 86400;
$end_of_day = ceil (time() / 86400) * 86400;

동일한 스크립트에 두 값이 모두 필요한 경우. 바닥과 천장을 모두 발사하는 것보다 변수 중 하나에 +/- 86400 초가 더 빠릅니다. 예를 들면 :

$start_of_day = floor (time() / 86400) * 86400;
$end_of_day = $start_of_day + 86400;
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.