如何将两个日期缩小到一个日期范围内?
How can I shrink two dates in to one date range?
我需要显示如下日期范围:
- 2015 年 5 月 5-7 日
- 2015年4月29日-5月5日
- 2015年12月30日-2016年1月1日
我以 PHP 日期对象的形式提供了开始日期和结束日期。有没有一种方法可以解析那些 PHP 以根据需要输出?
编辑:我认为你们误解了我要做什么。
我有一个输出开始日期和结束日期的 WordPress 事件插件。如果事件的开始日期为 2015 年 5 月 4 日,结束日期为 2015 年 5 月 7 日,我需要显示:
<h4>Event Title</h4>
<p>When: <time>May 4-7, 2015</time></p>
我不需要显示给定日期之间的每个日期;这很容易让我自己弄清楚。
编辑 2: 好吧,只是为了确保我完全清楚:
我正在使用 Tri.be 事件插件来允许用户创建事件日历。在这个 WordPress 站点的首页上,我需要显示即将发生的事件的列表。每个事件应该这样输出:

这个事件应该这样输出:
<article>
<h4><a href="/path/to/event/">Systematic Implementation of Advance Care Planning in a Diverse City</a></h4>
<p>
<a href="/path/to/event/">
Aging in America Conference - Chicago, IL<br />
<time datetime="2015-03-23">March 23-27, 2015</time>
</a>
</p>
</article>
我遇到的问题是 <time>
元素。下面的答案似乎表明我想以这种格式输出时间:
<time datetime="2015-03-23">March 23, 2015 - March 27, 2015</time>
这是不正确的。如果是这样的话,我可以很容易地自己输出这个。正确的格式是:
<time datetime="2015-03-23">March 23-27, 2015</time>
因此,问题是:"How can I shrink two dates in to one date range?"
这将是最简单的解决方案:
$dtStart = new DateTime('2015-05-05');
$dtEnd = new DateTime('2015-05-07');
while ($dtStart <= $dtEnd) {
echo $dtStart->format('Y-m-d') . "\n";
$dtStart->modify('+1 day');
}
// Output:
// 2015-05-05
// 2015-05-06
// 2015-05-07
$dtStart = new DateTime('2015-12-30');
$dtEnd = new DateTime('2016-01-01');
while ($dtStart <= $dtEnd) {
echo $dtStart->format('Y-m-d') . "\n";
$dtStart->modify('+1 day');
}
// Output:
// 2015-12-30
// 2015-12-31
// 2016-01-01
编辑 2:
我已经用一些日期格式更新了函数。
输出将是:
Event title
When: Feb 28, 2010 - Mar 2, 2010
Event title
When: Mar 4, 2010 - Mar 5, 2010
Event title
When: Dec 31, 2010 - Jan 5, 2011
编辑:
我找到了这个(通过搜索)--> Check for consecutive dates within a set and return as range
下面的代码不是我的。这是来自 @Darragh
的旧 post
I have made some minor changes to the code to fit the OP's question.
// assuming a chronologically
// ordered array of DateTime objects
$dates = array(
new DateTime('2010-02-28'),
new DateTime('2010-03-01'),
new DateTime('2010-03-02'),
new DateTime('2010-03-04'),
new DateTime('2010-03-05'),
new DateTime('2010-12-31'),
new DateTime('2011-01-01'),
new DateTime('2011-01-02'),
new DateTime('2011-01-03'),
new DateTime('2011-01-04'),
new DateTime('2011-01-05'),
);
// process the array
$lastDate = null;
$ranges = array();
$currentRange = array();
foreach ($dates as $date) {
if (null === $lastDate) {
$currentRange[] = $date;
} else {
// get the DateInterval object
$interval = $date->diff($lastDate);
// DateInterval has properties for
// days, weeks. months etc. You should
// implement some more robust conditions here to
// make sure all you're not getting false matches
// for diffs like a month and a day, a year and
// a day and so on...
if ($interval->days === 1) {
// add this date to the current range
$currentRange[] = $date;
} else {
// store the old range and start anew
$ranges[] = $currentRange;
$currentRange = array($date);
}
}
// end of iteration...
// this date is now the last date
$lastDate = $date;
}
// messy...
$ranges[] = $currentRange;
// print dates
foreach ($ranges as $range) {
// there'll always be one array element, so
// shift that off and create a string from the date object
$startDate = array_shift($range);
$str = "<h4>Event title</h4>";
$str .= "<p>When: ";
$str .= "<time>";
$str .= sprintf('%s', $startDate->format('M j, Y'));
// if there are still elements in $range
// then this is a range. pop off the last
// element, do the same as above and concatenate
if (count($range)) {
$endDate = array_pop($range);
$str .= sprintf(' - %s', $endDate->format('M j, Y'));
$str .= "</time></p>";
}
echo "<p>$str</p>";
}
旧答案(基于原始问题)。
$start_date = new DateTime( '2015-05-01' );
$end_date = new DateTime( '2015-05-04' );
$end_date = $end_date->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($start_date, $interval ,$end_date);
foreach($daterange as $date){
echo $date->format("M d, Y") . "<br>";
}
// Output
// May 01, 2015
// May 02, 2015
// May 03, 2015
// May 04, 2015
<article>
<h4><a href="/path/to/event/">Systematic Implementation of Advance Care Planning in a Diverse City</a></h4>
<p>
<a href="/path/to/event/">
Aging in America Conference - Chicago, IL<br />
<time datetime="2015-03-23/2015-03-27">March 23–27 2015</time>
</a>
</p>
</article>
编辑
使用上述 PHP 代码的完整示例。
Output
Mar 23, 2015–Mar 27, 2015
// assuming a chronologically
// ordered array of DateTime objects
$dates = array(
new DateTime('2015-03-23'),
new DateTime('2015-03-24'),
new DateTime('2015-03-25'),
new DateTime('2015-03-26'),
new DateTime('2015-03-27')
);
// process the array
$lastDate = null;
$ranges = array();
$currentRange = array();
foreach ($dates as $date) {
if (null === $lastDate) {
$currentRange[] = $date;
} else {
// get the DateInterval object
$interval = $date->diff($lastDate);
// DateInterval has properties for
// days, weeks. months etc. You should
// implement some more robust conditions here to
// make sure all you're not getting false matches
// for diffs like a month and a day, a year and
// a day and so on...
if ($interval->days === 1) {
// add this date to the current range
$currentRange[] = $date;
} else {
// store the old range and start anew
$ranges[] = $currentRange;
$currentRange = array($date);
}
}
// end of iteration...
// this date is now the last date
$lastDate = $date;
}
// messy...
$ranges[] = $currentRange;
// print dates
foreach ($ranges as $range) {
// there'll always be one array element, so
// shift that off and create a string from the date object
$startDate = array_shift($range);
$str = "<h4>Event title</h4>";
$str .= "<p>When: ";
$str .= "<time>";
$str .= sprintf('%s', $startDate->format('M j, Y'));
// if there are still elements in $range
// then this is a range. pop off the last
// element, do the same as above and concatenate
if (count($range)) {
$endDate = array_pop($range);
$str .= sprintf(' - %s', $endDate->format('M j, Y'));
$str .= "</time></p>";
}
}
echo "<time datetime=".$startDate->format('M j, Y')."/".$endDate->format('M j, Y').">".$startDate->format('M j, Y')."–".$endDate->format('M j, Y')."</time>";
//OUTPUT
// Mar 23, 2015–Mar 27, 2015
我需要显示如下日期范围:
- 2015 年 5 月 5-7 日
- 2015年4月29日-5月5日
- 2015年12月30日-2016年1月1日
我以 PHP 日期对象的形式提供了开始日期和结束日期。有没有一种方法可以解析那些 PHP 以根据需要输出?
编辑:我认为你们误解了我要做什么。
我有一个输出开始日期和结束日期的 WordPress 事件插件。如果事件的开始日期为 2015 年 5 月 4 日,结束日期为 2015 年 5 月 7 日,我需要显示:
<h4>Event Title</h4>
<p>When: <time>May 4-7, 2015</time></p>
我不需要显示给定日期之间的每个日期;这很容易让我自己弄清楚。
编辑 2: 好吧,只是为了确保我完全清楚:
我正在使用 Tri.be 事件插件来允许用户创建事件日历。在这个 WordPress 站点的首页上,我需要显示即将发生的事件的列表。每个事件应该这样输出:
这个事件应该这样输出:
<article>
<h4><a href="/path/to/event/">Systematic Implementation of Advance Care Planning in a Diverse City</a></h4>
<p>
<a href="/path/to/event/">
Aging in America Conference - Chicago, IL<br />
<time datetime="2015-03-23">March 23-27, 2015</time>
</a>
</p>
</article>
我遇到的问题是 <time>
元素。下面的答案似乎表明我想以这种格式输出时间:
<time datetime="2015-03-23">March 23, 2015 - March 27, 2015</time>
这是不正确的。如果是这样的话,我可以很容易地自己输出这个。正确的格式是:
<time datetime="2015-03-23">March 23-27, 2015</time>
因此,问题是:"How can I shrink two dates in to one date range?"
这将是最简单的解决方案:
$dtStart = new DateTime('2015-05-05');
$dtEnd = new DateTime('2015-05-07');
while ($dtStart <= $dtEnd) {
echo $dtStart->format('Y-m-d') . "\n";
$dtStart->modify('+1 day');
}
// Output:
// 2015-05-05
// 2015-05-06
// 2015-05-07
$dtStart = new DateTime('2015-12-30');
$dtEnd = new DateTime('2016-01-01');
while ($dtStart <= $dtEnd) {
echo $dtStart->format('Y-m-d') . "\n";
$dtStart->modify('+1 day');
}
// Output:
// 2015-12-30
// 2015-12-31
// 2016-01-01
编辑 2:
我已经用一些日期格式更新了函数。
输出将是:
Event title
When: Feb 28, 2010 - Mar 2, 2010
Event title
When: Mar 4, 2010 - Mar 5, 2010
Event title
When: Dec 31, 2010 - Jan 5, 2011
编辑:
我找到了这个(通过搜索)--> Check for consecutive dates within a set and return as range
下面的代码不是我的。这是来自 @Darragh
的旧 postI have made some minor changes to the code to fit the OP's question.
// assuming a chronologically
// ordered array of DateTime objects
$dates = array(
new DateTime('2010-02-28'),
new DateTime('2010-03-01'),
new DateTime('2010-03-02'),
new DateTime('2010-03-04'),
new DateTime('2010-03-05'),
new DateTime('2010-12-31'),
new DateTime('2011-01-01'),
new DateTime('2011-01-02'),
new DateTime('2011-01-03'),
new DateTime('2011-01-04'),
new DateTime('2011-01-05'),
);
// process the array
$lastDate = null;
$ranges = array();
$currentRange = array();
foreach ($dates as $date) {
if (null === $lastDate) {
$currentRange[] = $date;
} else {
// get the DateInterval object
$interval = $date->diff($lastDate);
// DateInterval has properties for
// days, weeks. months etc. You should
// implement some more robust conditions here to
// make sure all you're not getting false matches
// for diffs like a month and a day, a year and
// a day and so on...
if ($interval->days === 1) {
// add this date to the current range
$currentRange[] = $date;
} else {
// store the old range and start anew
$ranges[] = $currentRange;
$currentRange = array($date);
}
}
// end of iteration...
// this date is now the last date
$lastDate = $date;
}
// messy...
$ranges[] = $currentRange;
// print dates
foreach ($ranges as $range) {
// there'll always be one array element, so
// shift that off and create a string from the date object
$startDate = array_shift($range);
$str = "<h4>Event title</h4>";
$str .= "<p>When: ";
$str .= "<time>";
$str .= sprintf('%s', $startDate->format('M j, Y'));
// if there are still elements in $range
// then this is a range. pop off the last
// element, do the same as above and concatenate
if (count($range)) {
$endDate = array_pop($range);
$str .= sprintf(' - %s', $endDate->format('M j, Y'));
$str .= "</time></p>";
}
echo "<p>$str</p>";
}
旧答案(基于原始问题)。
$start_date = new DateTime( '2015-05-01' );
$end_date = new DateTime( '2015-05-04' );
$end_date = $end_date->modify( '+1 day' );
$interval = new DateInterval('P1D');
$daterange = new DatePeriod($start_date, $interval ,$end_date);
foreach($daterange as $date){
echo $date->format("M d, Y") . "<br>";
}
// Output
// May 01, 2015
// May 02, 2015
// May 03, 2015
// May 04, 2015
<article>
<h4><a href="/path/to/event/">Systematic Implementation of Advance Care Planning in a Diverse City</a></h4>
<p>
<a href="/path/to/event/">
Aging in America Conference - Chicago, IL<br />
<time datetime="2015-03-23/2015-03-27">March 23–27 2015</time>
</a>
</p>
</article>
编辑
使用上述 PHP 代码的完整示例。
Output
Mar 23, 2015–Mar 27, 2015
// assuming a chronologically
// ordered array of DateTime objects
$dates = array(
new DateTime('2015-03-23'),
new DateTime('2015-03-24'),
new DateTime('2015-03-25'),
new DateTime('2015-03-26'),
new DateTime('2015-03-27')
);
// process the array
$lastDate = null;
$ranges = array();
$currentRange = array();
foreach ($dates as $date) {
if (null === $lastDate) {
$currentRange[] = $date;
} else {
// get the DateInterval object
$interval = $date->diff($lastDate);
// DateInterval has properties for
// days, weeks. months etc. You should
// implement some more robust conditions here to
// make sure all you're not getting false matches
// for diffs like a month and a day, a year and
// a day and so on...
if ($interval->days === 1) {
// add this date to the current range
$currentRange[] = $date;
} else {
// store the old range and start anew
$ranges[] = $currentRange;
$currentRange = array($date);
}
}
// end of iteration...
// this date is now the last date
$lastDate = $date;
}
// messy...
$ranges[] = $currentRange;
// print dates
foreach ($ranges as $range) {
// there'll always be one array element, so
// shift that off and create a string from the date object
$startDate = array_shift($range);
$str = "<h4>Event title</h4>";
$str .= "<p>When: ";
$str .= "<time>";
$str .= sprintf('%s', $startDate->format('M j, Y'));
// if there are still elements in $range
// then this is a range. pop off the last
// element, do the same as above and concatenate
if (count($range)) {
$endDate = array_pop($range);
$str .= sprintf(' - %s', $endDate->format('M j, Y'));
$str .= "</time></p>";
}
}
echo "<time datetime=".$startDate->format('M j, Y')."/".$endDate->format('M j, Y').">".$startDate->format('M j, Y')."–".$endDate->format('M j, Y')."</time>";
//OUTPUT
// Mar 23, 2015–Mar 27, 2015