The 5th Annual China PHP Conference

相対的な書式

このページでは、 strtotime()DateTime そして date_create() のパーサーが理解する、 さまざまな相対日付/時刻フォーマットを説明します。

シンボル一覧
シンボル 書式
dayname 'sunday' | 'monday' | 'tuesday' | 'wednesday' | 'thursday' | 'friday' | 'saturday' | 'sun' | 'mon' | 'tue' | 'wed' | 'thu' | 'fri' | 'sat'
daytext 'weekday' | 'weekdays'
number [+-]?[0-9]+
ordinal 'first' | 'second' | 'third' | 'fourth' | 'fifth' | 'sixth' | 'seventh' | 'eighth' | 'ninth' | 'tenth' | 'eleventh' | 'twelfth' | 'next' | 'last' | 'previous' | 'this'
reltext 'next' | 'last' | 'previous' | 'this'
space [ \t]+
unit (('sec' | 'second' | 'min' | 'minute' | 'hour' | 'day' | 'fortnight' | 'forthnight' | 'month' | 'year') 's'?) | 'weeks' | daytext
日付に基づいた表記
書式 説明
'yesterday' 昨日の00:00:00 "yesterday 14:00"
'midnight' 時刻を00:00:00にします  
'today' 時刻を00:00:00にします  
'now' 今 - 単に無視されます  
'noon' 時刻を12:00:00にします "yesterday noon"
'tomorrow' 明日の00:00:00  
'back of' hour 指定された時の15分後 "back of 7pm", "back of 15"
'front of' hour 指定された時の15分前 "front of 5am", "front of 23"
'first day of' 現在月の最初の日にします。 この書式に続けて月名を指定する使いかたが最適です。 "first day of January 2008"
'last day of' 現在月の最後の日にします。 この書式に続いて月名を指定する使いかたが最適です。 "last day of next month"
ordinal space dayname space 'of' 現在月のx番目の曜日を計算します。 "first sat of July 2008"
'last' space dayname space 'of' 現在月の 最後の 曜日を計算します。 "last sat of July 2008"
number space? (unit | 'week') 値を数値で指定するような、相対的な時間指定を処理します。 "+5 weeks", "12 day", "-7 weekdays"
ordinal space unit 値を英単語で指定するような、相対的な時間指定を処理します。 "fifth day", "second month"
'ago' 直前に指定された相対的な時間指定について、正負反転します。 "2 days ago", "8 days ago 14:00", "2 months 5 days ago", "2 months ago 5 days", "2 days ago"
dayname 現在からみて次にやってくる、指定された曜日にします。 "Monday"
reltext space 'week' 特別な書式 "weekday + last/this/next week" を処理します。 "Monday next week"

注意:

相対的な記述は、相対的でない記述の 後で 処理されます。 このため、 "+1 week july 2008" と "july 2008 +1 week" とは同一になります。

ただし、 "yesterday"、 "midnight"、 "today"、 "noon" そして "tomorrow" はこのルールの例外です。 つまり、 "tomorrow 11:00" と "11:00 tomorrow" は異なります。 たとえば、今日が2008年7月23日だとしましょう。 このときの1つ目の結果は "2008-07-24 11:00" ですが、 2つ目の方は "2008-07-24 00:00" となります。 このような結果になる理由は、 これら5つの記述が現在時刻に直接影響するためです。

注意:

日付/時刻文字列中の曜日指定が現在の曜日と同じ場合は、 以下の点に注意してください。 この場合、日付文字列中の曜日は、曜日を明示的に指定しなかった場合に 日付文字列の相対的でない部分から計算される曜日と同一ではありますが、 指定しなくても同じというわけではありません。

  1. "dayname" は、 日付を進め ません 。 (例: "Wed July 23rd, 2008" は "2008-07-23" の意味です。)
  2. "number dayname" は、 日付を進めません 。 (例: "1 wednesday july 23rd, 2008" は "2008-07-23" の意味です。)
  3. "number week dayname" は、 指定された週を加算しますが、 さらに日付を進めることはしません。 この場合、"number week" と "dayname" は 2 つの別個のブロックとなります。 (例: "+1 week wednesday july 23rd, 2008" は "2008-07-30" の意味です。)
  4. "ordinal dayname" は、日付を別の日まで進めます。 (例: "first wednesday july 23rd, 2008" は "2008-07-30" の意味です。)
  5. "number week ordinal dayname" は、まず指定された週を加算し、 それから日付を別の日まで進めます。 この場合、 "number week" と "ordinal dayname" は2つの別個のブロックとなります。 (例: "+1 week first wednesday july 23rd, 2008" は "2008-08-06" の意味です。)
  6. "ordinal dayname 'of' " は日付を進め ません 。 (例: "first wednesday of july 23rd, 2008" は "2008-07-02" の意味です。 なぜなら、'of'を含む一連の語群 'first wednesday of july' が 相対的な書式として処理されることで 日付を同月の '1' 日にリセットしてしまい、'23rd' は無視されてしまうのです。)

また、書式 "ordinal space dayname space 'of' " と "'last' space dayname space 'of' " に含まれる "of" は少々特別扱いなので、注意してください。

  1. 日付を指定月の1日にします。
  2. "ordinal dayname 'of' " は日付を進め ません 。 (例: "first tuesday of july 2008" は "2008-07-01" の意味です。)
  3. "ordinal dayname " は日付を進め ます 。 (例: "first tuesday july 2008" は "2008-07-08" の意味です。上記の項番4を参照。)
  4. "'last' dayname 'of' " は、 指定された曜日(dayname)の同月最後の日を返します。 (例: "last wed of july 2008" は "2008-07-30" の意味です。)
  5. "'last' dayname" は、 現在日付からみて直前の、指定された曜日(dayname)を返します。 (例: "last wed july 2008" は "2008-06-25" の意味です。 まず "july 2008" を処理して現在日付を "2008-07-01" とみなし、 次に "last wed" により直前の水曜日、つまり "2008-06-25" へと移動します。)

注意:

月数を相対指定すると、その途中に経過する月の日数を使って結果を算出します。 たとえば "+2 month 2011-11-30" の結果は "2012-01-30" となります。 11 月の日数は 30 日、12 月の日数は 31 日なので、 その合計である 61 日後となるわけです。

変更履歴

バージョン 説明
5.6.23, 7.0.8 週の始まりが常に月曜日となりました。 これより前のバージョンでは、日曜日も週の始まりとみなされていました。
5.3.3 "first day" と "last day" が、それぞれ "+1 day" と "-1 day" のように振る舞うようになりました。以前はそれぞれ "first day of" と "last day of" でした。

add a note add a note

User Contributed Notes 11 notes

up
20
Mark Simon
1 year ago
Note that expressions such as “last day of” and “first day of” imply a day of a month, not, for example of the year or week.

So, expressions, such as “first day of this year” will give the first day of this month, with no apparent regard for the year.

As powerful as the parser is, it can lead to disappointing or confusing results.
up
9
oguzkonya34 at gmail dot com
5 years ago
April 1st, 2012 is Sunday. You might expect to get April 2nd, 2012 with 'Monday next week', however this:

<?php
   
echo date('F jS, Y', strtotime('Monday next week 2012-04-01'));
?>

returns April 9th, 2012. To get April 2nd, you need to use this:

<?php
   
echo date('F jS, Y', strtotime('next Monday 2012-04-01'));
?>

Apparently 'next week' advances the week if and only if the day is Sunday. This:

<?php
   
echo date('F jS, Y', strtotime('Monday next week 2012-03-31'));
?>

would still return April 2nd.
up
2
phpnet at rudde dot org
1 year ago
Get the first day of a month, in a typical calendar month, typically the Monday in the first week of the month. In my example when the code is ran at 2016-04-06, 1st of april will be a Friday, since Calendars typically start on monday, this is the date you might want, in this case this would be 28th of March.

<?php
/* Code ran at 2016-04-06 */
$date = new DateTime('first day of this month');
$date->modify('monday this week');

echo
$date->format('Y-m-d');
/* Output: 2016-03-28 */
?>
up
4
chris at burnhamup dot com
4 years ago
Using strtotime('DAYNAME') like strtotime('Tuesday') returns midnight on the specified day. It doesn't preserve the current time or the time passed into the function.
up
6
geneticdrift
6 years ago
Month skipping has issues with number of days in the month.

'+1 month' may move to the following month if the next month has less days than the current:

<?php print date('d M Y H:i:s', strtotime('+1 month', strtotime('Thu Mar 31 19:50:41 IST 2011'))); ?>
Prints: 01 May 2011 19:50:41

But with 'last day of +1 month' the result is different:

<?php print date('d M Y H:i:s', strtotime('last day of +1 month', strtotime('Thu Mar 31 19:50:41 IST 2011'))); ?>
Prints: 30 Apr 2011 19:50:41

(PHP 5.3.3)
up
1
php at rcs dot us
5 months ago
I'm not sure if this is a bug or expected. As erwin points out :

"first monday of may 2011" is invalid, but "first monday may 2011" does work. Simply omit "of" if above examples do not work.

This still applies in 5.5 as well, and I ran into it while building out a utility to check if a day was a holiday.

Meaning "fourth day July 2016" /works/, but "fourth day of July 2016" does not. It will return an error. I emphasize works, because "fourth day July 2016" actually returns 2016-07-05. So you'll need "third day July 2016" for the Fourth of July.

However, "Last Monday May 2016" and "Last Monday of May 2016" ( for Memorial Day ) are both /valid/, but produce different results. The first returns 2016-04-25, which is incorrect, while the second returns the correct 2016-05-30.
up
3
erwin at darcoury dot nl
5 years ago
In PHP 5.2, "first monday of may 2011" is invalid, but "first monday may 2011" does work. Simply omit "of" if above examples do not work.
up
0
shkkmo at gmail dot com
3 years ago
Here is a fairly simple function I wrote to avoid the issues with adding/subtracting months that has been mentioned by cristinawithout and many others.

I needed this function to be able handle monthly billing cycles properly. It handles positive and negative values for months. It also can be used to side step a similar issues for adding years on leap days (e.g. strtotime('2012/2/29 +1 year') by passing in multiples of 12 (e.g. addMonthsToTime(12, strtotime('2012/2/29'))

<?
function addMonthsToTime($numMonths = 1, $timeStamp = null){
    $timeStamp === null and $timeStamp = time();//Default to the present
    $newMonthNumDays =  date('d',strtotime('last day of '.$numMonths.' months', $timeStamp));//Number of days in the new month
    $currentDayOfMonth = date('d',$timeStamp);
    if($currentDayOfMonth > $newMonthNumDays){
      $newTimeStamp = strtotime('-'.($currentDayOfMonth - $newMonthNumDays).' days '.$numMonths.' months', $timeStamp);
    } else {
      $newTimeStamp = strtotime($numMonths.' months', $timeStamp);
    }
    return $newTimeStamp;
  }
?>
up
-1
matt
5 years ago
If the ordinal being used is "last" and the next month is n, use the "n 1". Otherwise, if the previous month is p and it has d number of days in it, use "p d".

For example: "last thursday of November" becomes "last thursday December 1" and "fourth thursday of November" becomes "fourth thursday September 30th"

Hopes this helps someone out there.
up
-7
scragar at gmail dot com
5 years ago
Just for those who want the last day of the year without calling the function twice:

<?php
echo date('Y-m-d',
   
strToTime('1/1 next year -1 day')
);
//   2011-12-31
?>

For reference this is actually saying "Take the first day of the first month next year, then subtract 1 day".
up
-9
Pseudoname
2 years ago
oguzkonya34 at gmail dot com
Point of correction:
Apparently 'next week' advances the week if and only if the day is Sunday. This:
<?php
   
echo date('F jS, Y', strtotime('Monday next week 2012-03-31'));
?>
would still return April 2nd.
Quote "
Apparently 'next week' advances the week if and only if the day is Sunday. "
Not really. 2012-03-31 would be Saturday if 2012-04-01 is Sunday as you mentioned. Then Monday next week for 2012-03-31 is April 2nd which is correct.
To Top