我正在尝试编写这样的日历函数
function get_date($month, $year, $week, $day, $direction)
{
....
}
$week
是一个整数 (1, 2, 3...),$day 是一天 (Sun, Mon, ...) 或数字,以更简单的为准。方向有点混乱,因为它进行了不同的计算。
举个例子,我们打电话给
get_date(5, 2009, 1, 'Sun', 'forward');
它使用默认值,并获取五月的第一个星期日,即2009-05-03。如果我们打电话
get_date(5, 2009, 2, 'Sun', 'backward');
,它返回五月的第二个最后一个星期日,即 2009-05-24。
与语言无关的版本:
要获取该月的第一天,请从该月的第一天开始:yyyy-mm-01。使用任何可用的函数来给出与星期几相对应的数字。从您要查找的日期减去该数字;例如,如果该月的第一天是星期三 (2),而您要查找星期五 (4),则从 4 中减去 2,剩下 2。如果答案是否定的,则添加 7。最后将其添加到第一个这个月;以我为例,第一个星期五将是第三个。
要获取该月的最后一个星期五,请找到下个月的第一个星期五并减去 7 天。
也许可以做得更快......
这对代码来说非常有趣。
请注意,
$direction
为 1 表示向前,-1 表示向后,以简化操作:)$day
周一的值从 1 开始,周日的值 7 结束。
function get_date($month, $year, $week, $day, $direction) {
if($direction > 0)
$startday = 1;
else
$startday = date('t', mktime(0, 0, 0, $month, 1, $year));
$start = mktime(0, 0, 0, $month, $startday, $year);
$weekday = date('N', $start);
if($direction * $day >= $direction * $weekday)
$offset = -$direction * 7;
else
$offset = 0;
$offset += $direction * ($week * 7) + ($day - $weekday);
return mktime(0, 0, 0, $month, $startday + $offset, $year);
}
我已经用几个例子对其进行了测试,似乎总是有效,但请务必仔细检查;)
PHP 的内置时间函数使这一切变得简单。
http://php.net/manual/en/function.strtotime.php
// Get first Friday of next month.
$timestamp = strtotime('first fri of next month');
// Get second to last Friday of the current month.
$timestamp = strtotime('last fri of this month -7 days');
// Format a timestamp as a human-meaningful string.
$formattedDate = date('F j, Y', strtotime('first wed of last month'));
请注意,我们始终希望确保已定义与
strtotime
一起使用的正确时区,以便 PHP 了解在何处计算相对于机器认为其所在时区的时间戳。
date_default_timezone_set('America/New_York');
$formattedDate = date('F j, Y', strtotime('first wed of last month +1 week'));
strtotime()可以帮助你。例如
<?php
$tsFirst = strtotime('2009-04-00 next friday');
$tsLast = strtotime('2009-05-01 last friday');
echo date(DATE_RFC850, $tsFirst), " | ", date(DATE_RFC850, $tsLast);
打印2009 年 4 月 3 日星期五 00:00:00 CEST | 2009 年 4 月 24 日星期五 00:00:00 CEST
无需计算或循环 - 使用 strtotime() 非常容易做到:
查找特定月份中特定日期的第 N 次或最后一次出现:
/////////////////////////////////////////////////////////////////
// Quick Code
/////////////////////////////////////////////////////////////////
// Convenience mapping.
$Names = array( 0=>"Sun", 1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thu", 5=>"Fri", 6=>"Sat" );
// Specify what we want
// In this example, the Second Monday of Next March
$tsInMonth = strtotime('March');
$Day = 1;
$Ord = 2;
// The actual calculations
$ThisMonthTS = strtotime( date("Y-m-01", $tsInMonth ) );
$NextMonthTS = strtotime( date("Y-m-01", strtotime("next month", $tsInMonth) ) );
$DateOfInterest = (-1 == $Ord)
? strtotime( "last ".$Names[$Day], $NextMonthTS )
: strtotime( $Names[$Day]." + ".($Ord-1)." weeks", $ThisMonthTS );
/////////////////////////////////////////////////////////////////
// Explanation
/////////////////////////////////////////////////////////////////
// Specify the month of which we are interested.
// You can use any timestamp inside that month, I'm using strtotime for convenience.
$tsInMonth = strtotime('March');
// The day of interest, ie: Friday.
// It can be 0=Sunday through 6=Saturday (Like 'w' from date()).
$Day = 5;
// The occurrence of this day in which we are interested.
// It can be 1, 2, 3, 4 for the first, second, third, and fourth occurrence of the day in question in the month in question.
// You can also use -1 to fine the LAST occurrence. That will return the fifth occurrence if there is one, else the 4th.
$Ord = 3;
////////////////////////////////////////////////////////////////
// We now have all the specific values we need.
// The example values above specify the 3rd friday of next march
////////////////////////////////////////////////////////////////
// We need the day name that corresponds with our day number to pass to strtotime().
// This isn't really necessary = we could just specify the string in the first place, but for date calcs, you are more likely to have the day number than the string itself, so this is convenient.
$Names = array( 0=>"Sun", 1=>"Mon", 2=>"Tue", 3=>"Wed", 4=>"Thu", 5=>"Fri", 6=>"Sat" );
// Calculate the timestamp at midnight of the first of the month in question.
// Remember $tsInMonth is any date in that month.
$ThisMonthTS = strtotime( date("Y-m-01", $tsInMonth ) );
// Calculate the timestamp at midnight of the first of the FOLLOWING month.
// This will be used if we specify -1 for last occurrence.
$NextMonthTS = strtotime( date("Y-m-01", strtotime("next month", $tsInMonth) ) );
// Now we just format the values a bit and pass them to strtotime().
// To find the 1,2,3,4th occurrence, we work from the first of the month forward.
// For the last (-1) occurence,work we work back from the first occurrence of the following month.
$DateOfInterest = (-1 == $Ord) ?
strtotime( "last ".$Names[$Day], $NextMonthTS ) : // The last occurrence of the day in this month. Calculated as "last dayname" from the first of next month, which will be the last one in this month.
strtotime( $Names[$Day]." + ".($Ord-1)." weeks", $ThisMonthTS ); // From the first of this month, move to "next dayname" which will be the first occurrence, and then move ahead a week for as many additional occurrences as you need.
echo date('Y-m-d',strtotime('last friday'));
function get_date($month, $year, $week, $day) {
# $month, $year: current month to search in
# $week: 0=1st, 1=2nd, 2=3rd, 3=4th, -1=last
# $day: 0=mon, 1=tue, ..., 6=sun
$startday=1; $delta=0;
if ($week < 0) {
$startday = date('t', mktime(0, 0, 0, $month, 1, $year)); # 28..31
$delta=1;
}
$start = mktime(0, 0, 0, $month, $startday, $year);
$dstart = date('w', $start)-1; # last of the month falls on 0=mon,6=sun
$offset=$day-$dstart; if ($offset<$delta){$offset+=7;}
$newday=$startday+$offset+($week*7);
return mktime(0, 0, 0, $month, $newday, $year);
}
这对我有用,并且基于与语言无关的版本:-) 只是太糟糕了,我需要做那个 delta 事情(因为如果该月的最后一天是想要的工作日,我们不需要减去 7)
使用
DateTime
类可以非常优雅地完成同样的任务。
$time_zone = new DateTimeZone('Europe/Ljubljana');
$first_friday_of_this_month = new DateTime('first Friday of this month', $time_zone);
$last_friday_of_this_month = new DateTime('last Friday of this month', $time_zone);
echo $first_friday_of_this_month->format('Y-m-d'); # 2015-11-06
echo $last_friday_of_this_month->format('Y-m-d'); # 2015-11-27
只需找出相关月份的第一天和最后一天(即2009年5月1日是星期五,2009年5月31日是星期日)我相信大多数PHP函数使用Monday=0,Sunday=6,因此星期五=4,所以你知道周日(6)-周五(4)=2,那么31-2=29,意味着这个月的最后一个周五是29号。对于第一个星期五,如果数字为负数,则加 7,如果数字为 0,则月份从星期五开始。
这似乎每次都很完美;它接受提供的任何日期并返回该月最后一个星期五的日期,即使是该月的第 5 个星期五也是如此。
function get_last_friday_of_month($inDate) {
$inDate = date('Y-m-24', strtotime($inDate));
$last_friday = date('Y-m-d',strtotime($inDate.' next friday'));
$next_friday = date('Y-m-d',strtotime($inDate.' next friday'));
if(date('m', strtotime($last_friday)) === date('m', strtotime($next_friday))){
$last_friday = $next_friday;
}else{
//
}
return $last_friday;
}
以下是最快的解决方案,您可以在所有条件下使用。如果你稍微调整一下,你还可以获得一周中整天的数组。
function findDate($date, $week, $weekday){
# $date is the date we are using to get the month and year which should be a datetime object
# $week can be: 0 for first, 1 for second, 2 for third, 3 for fourth and -1 for last
# $weekday can be: 1 for Monday, 2 for Tuesday, 3 for Wednesday, 4 for Thursday, 5 for Friday, 6 for Saturday and 7 for Sunday
$start = clone $date;
$finish = clone $date;
$start->modify('first day of this month');
$finish->modify('last day of this month');
$finish->modify('+1 day');
$interval = DateInterval::createFromDateString('1 day');
$period = new DatePeriod($start, $interval, $finish);
foreach($period AS $date){
$result[$date->format('N')][] = $date;
}
if($week == -1)
return end($result[$weekday]);
else
return $result[$weekday][$week];
}
$date = DateTime::createFromFormat('d/m/Y', '25/12/2016');
# find the third Wednesday in December 2016
$result = findDate($date, 2, 3);
echo $result->format('d/m/Y');
我希望这有帮助。
如果您需要任何进一步的信息,请告诉我。 ;)
这是我在项目中取得了一些成功的代码部分
$fromLastDay = array( '5' => 0, '4' => 6, '3' => 5, '2' => 4, '1' => 3, '0' => 2, '6' => 1 );
$to1stFriday = array( '5' => 0, '4' => 1, '3' => 2, '2' => 3, '1' => 4, '0' => 5, '6' => 6 );
$curr1stFriday = 1 + ( $to1stFriday[date("w", strtotime(date('Y-m-1')))]);
$currLastFriday = date('t') - $fromLastDay[date('w', strtotime(date('Y-m-t')))];
## Check for Friday
if ( date("w") != 5 ) {
echo "Check For FRIDAY execution: ".date("l")." the ". date("d")." is NOT a Friday in ".date("F, Y").".\n";
} else {
## It's Friday, do something...
}
## Check for the First Friday
if (date('j') != $curr1stFriday) {
echo "Check For FRIDAY execution: ".date("l")." the ". date("d")." is NOT the First Friday of ".date("F, Y").".\n";
} else {
## First Friday, do something...
}
## Check for the Last Friday
if (date('j') != $currLastFriday) {
echo "Check For FRIDAY execution: ".date("l")." the ". date("d")." is NOT the Last Friday of ".date("F, Y").".\n";
} else {
## Last Friday, do something...
}