PHP 5.3のdate_diff関数を使用せずに(私はPHP 5.2.17を使用しています)、これを行うための簡単で正確な方法はありますか?以下のコードのようなものを考えていますが、うるう年を説明する方法がわかりません。
$days = ceil(abs( strtotime('2000-01-25') - strtotime('2010-02-20') ) / 86400);
$months = ???;
私は人が何ヶ月であるかを計算しようとしています。
$date1 = '2000-01-25';
$date2 = '2010-02-20';
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);
$month1 = date('m', $ts1);
$month2 = date('m', $ts2);
$diff = (($year2 - $year1) * 12) + ($month2 - $month1);
丸1か月かどうかによっては、日もどこかに含めることをお勧めします。あなたがアイデアを得るといいのですが。
これは、クラスで作成した簡単な方法で、2つの特定の日付に関係する月数をカウントします。
public function nb_mois($date1, $date2)
{
$begin = new DateTime( $date1 );
$end = new DateTime( $date2 );
$end = $end->modify( '+1 month' );
$interval = DateInterval::createFromDateString('1 month');
$period = new DatePeriod($begin, $interval, $end);
$counter = 0;
foreach($period as $dt) {
$counter++;
}
return $counter;
}
これが私の解決策です。日付の年と月の両方をチェックし、違いを見つけます。
$date1 = '2000-01-25';
$date2 = '2010-02-20';
$d1=new DateTime($date2);
$d2=new DateTime($date1);
$Months = $d2->diff($d1);
$howeverManyMonths = (($Months->y) * 12) + ($Months->m);
このような:
$date1 = strtotime('2000-01-25');
$date2 = strtotime('2010-02-20');
$months = 0;
while (($date1 = strtotime('+1 MONTH', $date1)) <= $date2)
$months++;
echo $months;
までの日数を含める場合は、次を使用します。
$date1 = strtotime('2000-01-25');
$date2 = strtotime('2010-02-20');
$months = 0;
while (strtotime('+1 MONTH', $date1) < $date2) {
$months++;
$date1 = strtotime('+1 MONTH', $date1);
}
echo $months, ' month, ', ($date2 - $date1) / (60*60*24), ' days'; // 120 month, 26 days
これが私の解決策です。日付の年と月のみをチェックします。したがって、一方の日付がで31.10.15
、もう一方の日付が02.11.15
1か月である場合、それは1か月を返します。
function get_interval_in_month($from, $to) {
$month_in_year = 12;
$date_from = getdate(strtotime($from));
$date_to = getdate(strtotime($to));
return ($date_to['year'] - $date_from['year']) * $month_in_year -
($month_in_year - $date_to['mon']) +
($month_in_year - $date_from['mon']);
}
これが私がそれを解決することになった方法です。私は少し遅れていることを知っていますが、これによって誰かが多くの時間とコード行を節約できることを願っています。
DateInterval :: formatを使用して、人間が読めるカウントダウンクロックを年、月、日で表示しました。フォーマットテーブルについては、 https://www.php.net/manual/en/dateinterval.format.phpを確認して、戻り値を変更する方法に関するオプションを確認してください。あなたが探しているものをあなたに与えるべきです。
$origin = new DateTime('2020-10-01');
$target = new DateTime('2020-12-25');
$interval = $origin->diff($target);
echo $interval->format('%y years, %m month, %d days until Christmas.');
出力:0年、2か月、24日
私は最近、出生前から5歳(60か月以上)までの月数で年齢を計算する必要がありました。
上記の答えはどちらも私にはうまくいきませんでした。私が最初に試したのは、基本的にdecezeの答えのための1つのライナーです
$bdate = strtotime('2011-11-04');
$edate = strtotime('2011-12-03');
$age = ((date('Y',$edate) - date('Y',$bdate)) * 12) + (date('m',$edate) - date('m',$bdate));
. . .
これは設定された日付では失敗します。月のマーク(2011-12-04)にまだ達していないため、コードが1を返す場合でも、明らかに答えは0になるはずです。
Adamのコードを使用して試した2番目の方法
$bdate = strtotime('2011-01-03');
$edate = strtotime('2011-02-03');
$age = 0;
while (strtotime('+1 MONTH', $bdate) < $edate) {
$age++;
$bdate = strtotime('+1 MONTH', $bdate);
}
. . .
これは失敗し、1になるはずの0か月と表示されます。
私にとってうまくいったのは、このコードを少し拡張したことです。私が使用したのは次のとおりです。
$bdate = strtotime('2011-11-04');
$edate = strtotime('2012-01-04');
$age = 0;
if($edate < $bdate) {
//prenatal
$age = -1;
} else {
//born, count months.
while($bdate < $edate) {
$age++;
$bdate = strtotime('+1 MONTH', $bdate);
if ($bdate > $edate) {
$age--;
}
}
}
問題を解決するための私の機能
function diffMonth($from, $to) {
$fromYear = date("Y", strtotime($from));
$fromMonth = date("m", strtotime($from));
$toYear = date("Y", strtotime($to));
$toMonth = date("m", strtotime($to));
if ($fromYear == $toYear) {
return ($toMonth-$fromMonth)+1;
} else {
return (12-$fromMonth)+1+$toMonth;
}
}
私の解決策は、いくつかの答えを組み合わせることでした。特に$interval->diffにすべてのデータがある場合は、ループを実行したくありませんでした。計算を実行しただけで、私の場合は月数が負になる可能性があるため、これが私のアプローチでした。
/**
* Function will give you the difference months between two dates
*
* @param string $start_date
* @param string $end_date
* @return int|null
*/
public function get_months_between_dates(string $start_date, string $end_date): ?int
{
$startDate = $start_date instanceof Datetime ? $start_date : new DateTime($start_date);
$endDate = $end_date instanceof Datetime ? $end_date : new DateTime($end_date);
$interval = $startDate->diff($endDate);
$months = ($interval->y * 12) + $interval->m;
return $startDate > $endDate ? -$months : $months;
}
@decezeの回答をフォローアップします(私は彼の回答に賛成しました)。最初の日付の日が2番目の日付の日に達していない場合でも、月は全体としてカウントされます。
これがその日を含めるための私の簡単な解決策です:
$ts1=strtotime($date1);
$ts2=strtotime($date2);
$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);
$month1 = date('m', $ts1);
$month2 = date('m', $ts2);
$day1 = date('d', $ts1); /* I'VE ADDED THE DAY VARIABLE OF DATE1 AND DATE2 */
$day2 = date('d', $ts2);
$diff = (($year2 - $year1) * 12) + ($month2 - $month1);
/* IF THE DAY2 IS LESS THAN DAY1, IT WILL LESSEN THE $diff VALUE BY ONE */
if($day2<$day1){ $diff=$diff-1; }
ロジックは、2番目の日付の日が最初の日付の日よりも小さい場合、$diff
変数の値を1つ減らします。
これはどう:
$d1 = new DateTime("2009-09-01");
$d2 = new DateTime("2010-09-01");
$months = 0;
$d1->add(new \DateInterval('P1M'));
while ($d1 <= $d2){
$months ++;
$d1->add(new \DateInterval('P1M'));
}
print_r($months);
$date1 = '2000-01-25';
$date2 = '2010-02-20';
$ts1 = strtotime($date1);
$ts2 = strtotime($date2);
$year1 = date('Y', $ts1);
$year2 = date('Y', $ts2);
$month1 = date('m', $ts1);
$month2 = date('m', $ts2);
$diff = (($year2 - $year1) * 12) + ($month2 - $month1);
月が1月から2月に切り替わった場合、上記のコードは$ diff = 1を返しますが、翌月を30日後にのみ検討する場合は、上記に加えて以下のコード行を追加します。
$day1 = date('d', $ts1);
$day2 = date('d', $ts2);
if($day2 < $day1){ $diff = $diff - 1; }
2つの日付の間のカレンダー月数(ここでも尋ねられます)を計算するために、私は通常、このようなことをすることになります。2つの日付を「2020-05」や「1994-05」のような文字列に変換し、以下の関数からそれぞれの結果を取得して、それらの結果の減算を実行します。
/**
* Will return number of months. For 2020 April, that will be the result of (2020*12+4) = 24244
* 2020-12 = 24240 + 12 = 24252
* 2021-01 = 24252 + 01 = 24253
* @param string $year_month Should be "year-month", like "2020-04" etc.
*/
static private function calculate_month_total($year_month)
{
$parts = explode('-', $year_month);
$year = (int)$parts[0];
$month = (int)$parts[1];
return $year * 12 + $month;
}
function date_duration($date){
$date1 = new DateTime($date);
$date2 = new DateTime();
$interval = $date1->diff($date2);
if($interval->y > 0 and $interval->y < 2){
return $interval->y.' year ago';
}else if($interval->y > 1){
return $interval->y.' years ago';
}else if($interval->m > 0 and $interval->m < 2){
return $interval->m.' month ago';
}else if($interval->m > 1){
return $interval->y.' months ago';
}else if($interval->d > 1){
return $interval->d.' days ago';
}else{
if($interval->h > 0 and $interval->h < 2){
return $interval->h.' hour ago';
}else if($interval->h > 1){
return $interval->h.' hours ago';
}else{
if($interval->i > 0 and $interval->i < 2){
return $interval->i.' minute ago';
}else if($interval->i > 1){
return $interval->i.' minutes ago';
}else{
return 'Just now';
}
}
}
}
11か月前、2年前、5分前の日付の区別のスタイルを返します
例:
echo date_duration('2021-02-28 14:59:00.00');
現在の月に応じて「1か月前」に戻ります
自分が書いた関数を共有したいだけです。関連する日時形式を入力して修飾子akamodify( "+ 1 something")を定義することにより、月と年の両方を取得するように変更できます。
/**
* @param DateTimeInterface $start a anything using the DateTime interface
* @param DateTimeInterface|null $end to calculate the difference to
* @param string $modifier for example: day or month or year.
* @return int the count of periods.
*/
public static function elapsedPeriods(
DateTimeInterface $start,
DateTimeInterface $end = null,
string $modifier = '1 month'
): int
{
// just an addition, in case you just want the periods up untill now
if ($end === null ) {
$end = new DateTime();
}
// we clone the start, because we dont want to change the actual start
// (objects are passed by ref by default, so if you forget this you might
// mess up your data)
$cloned_start = clone $start;
// we create a period counter, starting at zero, because we want to count
// periods, assuming the first try, makes one period.
// (week, month, year, et cetera)
$period_count = 0;
// so while our $cloned_start is smaller to the $end (or now).
// we will increment the counter
while ($cloned_start < $end) {
// first off we increment the count, for the first iteration could end
// the cycle
$period_count++;
// now we modify the cloned start
$cloned_start->modify(sprintf("+1 %s", $modifier));
}
return $period_count; // return the count
}
乾杯