PHP 한 달, 일주일 더하고 빼기 strtotime()

strototime() 함수는 문자열 자료형으로 된 날짜를 날짜-시간 자료형으로 바꾸어주는 함수이다. 그 외에도 간단한 날짜 연산의 기능이 있는데 수식으로 하는 게 아닌 텍스트로 연산하는 특이한 기능이 있다. 한 달, 일주일 더하고 빼는데 유용하며 특정 계산구간에서는 버그가 일어나니 사용에 주의가 필요하다.

strtotime() 실무 활용사례

달마다 기말재고, 기초재고 테이블을 생성하는 과정에 특정한 달의 첫날 부터 마지막날 까지의 입출고 기록을 SQL로 검색해서 가져와야 했다. 2022년 11월 데이터를 불러온다면 날짜가 2022년 11월 1일보다 크거나 같고 2022년 12월 1일보다 작은 데이터를 모두 불러오면 된다. 11월 1일을 입력받고 자동으로 12월 1일을 연산하기 위해 strtotime()을 사용하였다.

SQL 구문으로 쓰자면

SELECT * FROM `inventoryCalc` WHERE `prodcode` = '096619356195' AND `appTime` >= '2022-11-1' AND `appTime` < '2022-12-1';

위 SQL구문은 `inventoryCalc` 라는 테이블에서 상품코드 096619356195 의 2022년 7월 입출고 데이터를 불러오는 구문이다.

웹페이지 유저로부터 2022년 11월 1일을 입력받으면 자동으로 2022년 8월 1일을 계산해 내야 하는데 월마다 날짜가 다르니 무턱대고 30일이나 31일을 더할수도 없다.

strtotime()함수를 활용하면 한 달, 일주일을 더하고 빼는 텍스트를 입력해서 날짜 계산을 할 수 있다.

예제 : 한 달 더하기

$appTime = '2022-11-1';
$time = date("Y-m-d H:i:s",strtotime("+1 month", strtotime($appTime)));
echo $time;

위 코드의 실행 결과로

2022-12-01 00:00:00

이 출력된다.

strtotime함수안에 strtotime함수가 한 번 더 쓰인 것이 보이는데 $appTime으로 정의한 변수는 날짜형식 데이터가 아닌 문자열(String) 형식이기에 날짜연산을 위해서 이 문자열을 시간형으로 한 번 바꿔주어야 한다.

이렇게 strtotime함수는 문자열로 표현된 시간을 시간형으로 바꾸어주는 역할도 한다.

예제 : 일주일 더하기

$appTime = '2022-11-1';
$time = date("Y-m-d H:i:s",strtotime("+1 week", strtotime($appTime)));
echo $time;

출력 결과

2022-11-08 00:00:00

또는 아래처럼 날짜에 바로 604800을 더해도 된다. 일주일이 605,800초이다.

$appTime = '2022-11-1';
$time = strtotime($appTime) + 604800;
echo date("Y-m-d H:i:s", $time);

출력 결과

2022-11-08 00:00:00

실무 예제 : SQL구문 안에 넣기

한 달만 더하는 것을 반복적으로 써야하기에 monthpp라는 함수를 정의해서 묶어버렸다.

아래 코드는 특정 상품코드(096619356195)의 2022년 11월 1일 ~ 2022년 11월 31일 (2022년 12월 1일보다 작은)의 입출고 데이터를 불러오는 코드이다.

매월 기말 기초재고 계산을 위한 PHP 코드 중 일부이다.

프로젝트 특성상 그달의 가장 마지막 데이터만 필요해서 시간 (appTime)의 내림차순 정렬 (DESC)로 불러왔다.

function monthpp($appTime){
  $time = date("Y-m-d H:i:s",strtotime("+1 month", strtotime($appTime)));
  return $time;
}
$prodcode = '096619356195';
$begin = '2022-11-1';


 include "db.php";
 $sql = "SELECT * FROM `inventoryCalc` WHERE `prodcode` = '".$prodcode."' AND `appTime` >= '".$begin."' AND `appTime` < '".monthpp($begin)."' ORDER BY `appTime` DESC;";
 $result = mysqli_query($conn, $sql);

strtotime() 그 외의 기능

위 코드의 “+1 month”텍스트를 적은 부분에 다른 포멧의 텍스트를 적어넣으면 또 다른 계산을 할 수 있다.

아래 코드 예, 결과 예시는 모두
$time = strtotime(‘2022-12-21 23:43:32’);
으로 정의하고 실행한 결과이다.

형식설명코드 예결과 예
yesterday어제 자정을 출력echo date(“Y-m-d H:i:s”,strtotime(“yesterday”,$time));2022-12-20 00:00:00
midnight오늘 자정을 출력echo date(“Y-m-d H:i:s”,strtotime(“midnight”,$time));2022-12-21 00:00:00
today오늘 자정echo date(“Y-m-d H:i:s”,strtotime(“today”,$time));2022-12-21 00:00:00
nowecho date(“Y-m-d H:i:s”,strtotime(“now”));2022-12-21 23:43:32
(현재시간 출력)
noonyesterday noon의 형식으로도 사용 가능echo date(“Y-m-d H:i:s”,strtotime(“noon”,$time));

echo date(“Y-m-d H:i:s”,strtotime(“yesterday noon”,$time));
2022-12-21 12:00:00

2022-12-20 12:00:00
tomorrow내일 자정echo date(“Y-m-d H:i:s”,strtotime(“tomorrow”,$time));2022-12-22 00:00:00
first day of그 달의 첫날echo date(“Y-m-d H:i:s”,strtotime(“first day of Dec 2022”,$time));2022-12-01 00:00:00
last day of그 달의 마지막 날echo date(“Y-m-d H:i:s”,strtotime(“last day of Dec 2022”,$time));2022-12-31 00:00:00
of특정 요일표시echo date(“Y-m-d H:i:s”,strtotime(“first sat of December 2022”,$time));2022-12-03 00:00:00

주의사항 버그

내장함수인데 기가 막힌 버그가 하나 있다.

$time = strtotime('2023-3-31');
echo date("Y-m-d",strtotime("-1 month",$time));

위 코드는 2023-2-28을 출력하기를 기대하고 작성한 코드이다.

실제 결과를 보면

2023-03-03

???

2023-3-3이 출력되는 어이없는 결과가 나온다.

알려진 바에 따르면 -1 month 연산을 하면 전 달의 일수만큼 빼는 로직이라 생기는 버그라고 한다.

더 놀라운 것은 내장함수의 버그가 알려진지 수십 년이 되었는데도 아직 고쳐지지 않고 있다는 사실이다.

서드파티 함수를 구해서 사용하거나 정확한 함수를 직접(…) 만들어 사용하여야한다. 윤년 계산까지 넣으려니 번거로워서 내가 쓰는 구간에서는 버그가 발생하지 않으니 일단 strtotime() 내장함수를 사용했다.

+1 month 연산은 매월 말일에 +1 month를 하면 이런 버그를 볼 수 있다.

2021-1-31에 +1 month 연산을 돌리면 출력이 2021-3-3 로 나온다.

매월 초에 +1 month 연산만 사용하고 있기에 버그가 일어나진 않지만 썩 유쾌하진 않다.

관련 글

Leave a Comment