web-dev-qa-db-ja.com

strtotimeとdateを使用して、今日に関連する前の月と年を取得する方法は?

現在の日付と比較して、前の月と年を取得する必要があります。

ただし、次の例を参照してください。

_// Today is 2011-03-30
echo date('Y-m-d', strtotime('last month'));

// Output:
2011-03-02
_

2月と3月の日数が異なるため、この動作は(ある程度まで)理解できます。上記の例のコードは必要なものですが、毎月1日から28日の間は100%しか正しく動作しません。

それで、先月と年(date("Y-m")のことを考えて)を可能な限り最もエレガントな方法で取得する方法は、それが年中毎日機能しますか?最適なソリューションは、strtotime引数の解析に基づいています。

更新。要件を少し明確にするため。

過去2か月の統計を取得するコードがありますが、最初に先月の統計を表示し、必要に応じて他の月を読み込みます。それは意図した目的です。そのため、この月の間に、前の月の統計情報を読み込むためにどの月年を取得する必要があるかを調べたいと思います。

また、タイムゾーンを認識し(現時点ではあまり重要ではない)、入力としてstrtotime互換文字列を受け入れ(内部日付を初期化する)、日付/時刻を調整できるコードもあります。 strtotime互換の文字列を使用します。

私はそれがいくつかの条件と基本的な数学で行うことができることを知っていますが、これはたとえばこれと比較して本当に厄介です(もちろん正しく動作した場合):

_echo tz::date('last month')->format('Y-d')
_

したがって、strtotime互換の形式で、前の月と年のみが必要です。

回答(ありがとう、@ dnagirl):

_// Today is 2011-03-30
echo date('Y-m-d', strtotime('first day of last month')); // Output: 2011-02-01
_
56
mr.b

DateTime クラスをご覧ください。計算は正しく行われ、日付形式はstrttotimeと互換性があります。何かのようなもの:

$datestring='2011-03-30 first day of last month';
$dt=date_create($datestring);
echo $dt->format('Y-m'); //2011-02
48
dnagirl

日自体が重要でない場合は、これを行います:

echo date('Y-m-d', strtotime(date('Y-m')." -1 month"));
27
ITroubs

今日同じ問題を抱えていたので、私は答えを見つけました。それは31日です。これは phpのバグ ではありませんが、期待される機能です(それ以降)。これによれば post strtotimeが実際に行うことは、月を1つ戻し、日数を変更しないことです。 5月31日の今日のイベントでは、無効な日付である4月31日を探しています。そのため、4月30日にかかってから1日追加され、5月1日になります。

2011-03-30の例では、1か月が2月30日に戻りますが、2月は28日しかないため無効です。次に、それらの日数の差(30-28 = 2)を取得し、2月28日(3月2日)の2日後に移動します。

他の人が指摘しているように、「先月」を取得する最良の方法は、strtotimeまたはDateTimeオブジェクトを使用して「最初の日」または「最後の日」を追加することです。

// Today being 2012-05-31
//All the following return 2012-04-30
echo date('Y-m-d', strtotime("last day of -1 month"));
echo date('Y-m-d', strtotime("last day of last month"));
echo date_create("last day of -1 month")->format('Y-m-d'); 

// All the following return 2012-04-01
echo date('Y-m-d', strtotime("first day of -1 month")); 
echo date('Y-m-d', strtotime("first day of last month"));
echo date_create("first day of -1 month")->format('Y-m-d');

したがって、これらを使用すると、クエリなどを作成する場合に日付範囲を作成することができます。

23
SeanDowney

特定の日付を基準に前の年と月を取得し、DateTimeを利用できるようにするには、次のようにします。

$d = new DateTime('2013-01-01', new DateTimeZone('UTC')); 
$d->modify('first day of previous month');
$year = $d->format('Y'); //2012
$month = $d->format('m'); //12
9
Timo Huovinen
date('Y-m', strtotime('first day of last month'));
7
Marek

strtotimeには2番目のtimestampパラメーターがあり、最初のパラメーターを2番目のパラメーターに対して相対的にします。だからあなたはこれを行うことができます:

date('Y-m', strtotime('-1 month', time()))
6
dieend

私が質問を正しく理解していれば、先月とその年が欲しいだけです:

<?php

  $month = date('m');
  $year = date('Y');
  $last_month = $month-1%12;
  echo ($last_month==0?($year-1):$year)."-".($last_month==0?'12':$last_month);

?>

以下に例を示します。 http://codepad.org/c99nVKG8

5
Neal

えー、ある人が言ったようにバグではありません。 1か月の日数はしばしば異なるため、これは予想される動作です。 strtotimeを使用して前月を取得する最も簡単な方法は、おそらく今月の最初から-1か月を使用することです。

$date_string = date('Y-m', strtotime('-1 month', strtotime(date('Y-m-01'))));
4
dqhendricks

Strtotime関数にバグを見つけたと思います。これを回避しなければならないときはいつでも、月/年の値について数学をしていることに常に気づきます。次のようなものを試してください:

$LastMonth = (date('n') - 1) % 12;
$Year      =  date('Y') - !$LastMonth;
2
Zach Rattner

これは、前の月の日数が現在の月より少ないためです。これを修正するには、まず前月の日数が現在より少ないかどうかを確認し、それに基づいて計算を変更しました。

日数が少ない場合は-1か月の最終日を取得し、そうでない場合は現在の日を-1か月取得します。

if (date('d') > date('d', strtotime('last day of -1 month')))
{
    $first_end = date('Y-m-d', strtotime('last day of -1 month'));
}
else
{
    $first_end = date('Y-m-d', strtotime('-1 month'));
}
1
RJD22

おそらくあなたが望んでいるよりも少し長めですが、読みやすくするために必要以上に多くのコードを使用しました。

とはいえ、それはあなたが得ているのと同じ結果をもたらします-あなたがそれを出して欲しい/期待するものは何ですか?

//Today is whenever I want it to be.
$today = mktime(0,0,0,3,31,2011);

$hour   = date("H",$today);
$minute = date("i",$today);
$second = date("s",$today);
$month  = date("m",$today);
$day    = date("d",$today);
$year   = date("Y",$today);

echo "Today: ".date('Y-m-d', $today)."<br/>";
echo "Recalulated: ".date("Y-m-d",mktime($hour,$minute,$second,$month-1,$day,$year));

月と年だけが必要な場合は、「今日」の日をとるのではなく、単に「01」に設定します。

 $day = 1;

必要なものが得られるはずです。時間、分、秒をゼロに設定するだけで、それらを使用する必要はありません。

 date("Y-m",mktime(0,0,0,$month-1,1,$year);

かなり削減します;-)

1
Codecraft
//return timestamp, use to format month, year as per requirement
function getMonthYear($beforeMonth = '') {
    if($beforeMonth !="" && $beforeMonth >= 1) {
        $date = date('Y')."-".date('m')."-15";
        $timestamp_before = strtotime( $date . ' -'.$beforeMonth.' month' );
        return $timestamp_before;
    } else {
        $time= time();
        return $time;
    }
}


//call function
$month_year = date("Y-m",getMonthYear(1));// last month before  current month
$month_year = date("Y-m",getMonthYear(2)); // second last month before current month
0
Mukesh

DateTimeソリューションが受け入れられる場合、このスニペットは、1月にこれを実行したときに起こりうるトラップを回避して、先月の年と先月の月を返します。

function fn_LastMonthYearNumber()
{
 $now = new DateTime();
 $lastMonth = $now->sub(new DateInterval('P1M'));
 $lm= $lastMonth->format('m');
 $ly= $lastMonth->format('Y');
 return array($lm,$ly);
}
0
zzapper
function getOnemonthBefore($date){
    $day = intval(date("t", strtotime("$date")));//get the last day of the month
    $month_date = date("y-m-d",strtotime("$date -$day days"));//get the day 1 month before
    return $month_date;
}

結果の日付は、入力月が含まれる日数に依存します。入力月が2月(28日)の場合、2月5日の28日前は1月8日です。入力が17日の場合、31日前は4月16日です。同様に、入力が31日の場合、結果の日付は4月30日です。

[〜#〜] note [〜#〜]:入力には完全な日付( 'y-m-d')と出力( 'y-m-d')が必要です。必要に応じてこのコードを変更できます。

0