So I'm making a website for this pizzeria.
In the past I made a simple window that pops up Monday-Friday & Between 11.30am-02:00pm which is simple enough.
But now I've had a request to do the same thing, but instead of having a single "Lunch Buffe Ongoing!" box, the client want's a daily menu (different menu every day, which is also easy enough), but he has 3 different daily menus alternating every week.
So here's an example:
Week 1 Menu:
Monday: w1m1
Tuesday: w1m2
..
Week 2 Menu:
Monday: w2m1
Tuesday: w2m2
So my question is:
Is there a PHP function / equation for calculating "is it the first, second or third" week from a specified starting date
Edit (Not duplicate because):
This isn't a duplicate of PHP get number of week for month because I'm not asking for the week number, I'm asking what week this is alternating with 3
Answer:
<?php
function menuNumber($now) {
$then = '26/05/2014';
$first = DateTime::createFromFormat('d/m/Y', $then);
$second = DateTime::createFromFormat('d/m/Y', $now);
$calculated = (floor($first->diff($second)->days/7) % 3) + 1;
return $calculated;
}
echo "Menu Number " . menuNumber(date("d/m/Y")); // Menu Number 1
?>
Help From:
php weeks between 2 dates
PHP
<?php
function menuNumber($now) {
$then = '26/05/2014';
$first = DateTime::createFromFormat('d/m/Y', $then);
$second = DateTime::createFromFormat('d/m/Y', $now);
$calculated = (floor($first->diff($second)->days/7) % 3) + 1;
return $calculated;
}
echo "Menu Number " . menuNumber(date("d/m/Y")); // Menu Number 1
?>
Help From: PHP weeks between 2 dates
Related
In the Christian liturgical year, Advent starts things off four weeks before Christmas, and there are three cycles (Year A, B, and C).
In PHP, what would be the most efficient and elegant method to determine what cycle we would be in for any given year.
Here are the rules:
The beginning of the cycle occurs on whatever Sunday falls on or closest to Nov. 30
November 30, 2016 was the beginning of year A.
There are three iterations, being year A, year B, and year C, after which we return to year A.
So if given any year month and day, would it be possible to determine whether that date was in the cycle A, B, or C?
UPDATE: What I've tried
I'm not very good with math, so haven't had much luck in figuring this out.
I've been focusing first on the year and how it relates to A B and C.
So if I equate A to 1 and B to 2 and C to 3, I could get the first three years by subtracting 2015 from the current date - but I don't know what to do after 2018.
To calculate the year, I think this would work:
$year = date('Y');
$year_A = strtotime(date('Y', strtotime('-1 year', strtotime($year))));
if($year % 3 == 0) {
$liturgical_year = "C" ;
} else if ($year_A % 3 == 0) {
$liturgical_year = "A" ;
} else {
$liturgical_year = "B" ;
}
echo $liturgical_year;
Also, to calculate the first date of the Liturgical year you can use St Andrew's feast day and find the closest Sunday:
$St_Andrew = date("Y") . "-11-30";
$St_Andrew = date($St_Andrew);
$last_Sunday = date('Y-m-d', strtotime('last Sunday', strtotime($St_Andrew)));
$next_Sunday = date('Y-m-d', strtotime('next Sunday', strtotime($St_Andrew)));
$days_delta = abs(strtotime($St_Andrew) - strtotime($last_Sunday))/(60 * 60 * 24);
if ($days_delta <= 3) {
$advent = $last_Sunday;
} else {
$advent = $next_Sunday;
}
Thanks to #Qirel for pointing me in the right direction. I've never really used the modulus operator before!
So problem is solved as follows (though my coding might be sloppy / inefficient):
$cycle = array(1=>"A",2=>"B",3=>"C");
for($year=2016;$year<2120;$year++){
$date = strtotime("Nov 30, " . $year);
echo "Sunday closest to " . date("Y-m-d",$date) . " is ";
$date = new DateTime($year . "/11/30 -4 days");
$date->modify("next Sunday");
echo $date->format("Y-d-m");
echo " where we start Year " . $cycle[(($year % 3) + 1)] . "<br/>";
}
Here's what's going on:
$cycle is defined as an array, where numbers 1, 2, and 3 are associated with years A, B, and C.
I then start a for loop to work through the years 2016 to 2120, incrementing the years by 1 on each iteration.
I then create a date of XXXX Nov 30 minus 4 days, where XXXX is the year we're iterating through. The minus four days helps us to be sure we're considering the date closest to the 30th, so that when we modify it in the following line to "next Sunday" it will always be the one closest to the 30th.
We then use the array $cycle, divide the year by 3 and take the remainder (using the modulus operator) which gives us either 0, 1, or 2 as an answer. I add one to it so it's returning 1, 2, or 3.
That isn't really necessary if I assign 0=>A, 1=>B, and 2=>C but...
I wrote a function to return this information:
function returnLiturgicalYear($year){
$cycle = array(0=>"A",1=>"B",2=>"C");
$date = new DateTime($year . "/11/30 -4 days");
$date->modify("next Sunday");
return $cycle[($year % 3)];
}
Hopefully this helps someone else trying to determine the Christian liturgical year for any date.
CONTEXT: My client, a local movie theater, runs a Sunday Matinee Special every other Sunday starting with the SECOND SUNDAY every year. So for this year the dates are 1/11, 1/18, 2/8, 2/22, .... [The only exception is the SUNDAY after their film festival which runs the the THIRD FULL WEEK OF OCTOBER, but automating this single exception is a "would-be-nice" item, not essential.]
MY SKILL LEVEL: BEGINNER (I need your help!) I believe I need to use a combination of mktime() and date() but I don't know how to put it together.
WHAT I'VE TRIED: I suspect the answer is a combination of what I see on these three posts:
(1) a do-while loop to get a specific day of the week from a date range
(2) there may be a shortcut for referencing the second sunday in the ACCEPTED ANSWER here, but I'm not sure this helps
(3) MOST RELEVANT(?): Get the First Sunday of Every Month
END RESULT: I want to display the [Month] and [Day] of the next Sunday Matinee (so I want to find and display the first item in the array AFTER the current date). The text will appear like this: "Next: [Month] [Day]"
Make sense? Let me know if I've forgotten anything.
If it's not too much to ask, please explain your code so I (and others?) can learn from this; but I'd be more than grateful for "merely" a straight-up solution.
Many thanks.
Debra
UPDATE/PROGRESS: This code will get me the array of Sundays:
$startDate = strtotime("second Sunday of ".date('Y')."");
for ($i=0; $i < 27; $i++){
$sundays = date('F j', ($startDate + (($i*14) * 24 * 3600))) . '<br>';
print $sundays;
}
NEXT TO FIGURE OUT: write a statement to find in the array of Sundays the first date after the current date.
This is a pretty manual, procedural solution, but it should work.
<?php
$SECS_PER_DAY = 86400;
# Find the first Sunday on or after a given timestamp
function firstSundayOnOrAfter($time) {
global $SECS_PER_DAY;
# What day of the week is the given date?
$wday = date('w', $time);
if ($wday == 0) {
# it's already a Sunday
return $time;
}
return $time + (7 - $wday) * $SECS_PER_DAY;
}
# return an array of timestamps representing
# (noon on) the special matinee Sundays for the given year
function specialMatineeSundays($year) {
global $SECS_PER_DAY;
# When's the film festival?
$oct1 = mktime(12,0,0,10,1,$year);
$festivalStart = firstSundayOnOrAfter($oct1);
$festivalSkip = $festivalStart + 7 * $SECS_PER_DAY;
# find the first Sunday of the year
$jan1 = mktime(12,0,0,1,1,$year);
$sunday = firstSundayOnOrAfter($jan1);
# Add a week to start with the second Sunday
$sunday += 7 * $SECS_PER_DAY;
# Build up our result list
$result = [];
# As long as the Sunday under examination is still the same year,
# add it to the list (unless it's the post-festival skip date)
# and then add two weeks
while (date('Y',$sunday) == $year) {
if ($sunday != $festivalSkip) {
$result[] = $sunday;
}
$sunday += 14 * $SECS_PER_DAY;
}
return $result;
}
Good Day,
I am trying to create a recurring date system that has the following:
nth day of nth month (2nd day of every 3rd month)
$this_months_friday = strtotime('+3 days +4 months');
the output of that will always be current day + 3 days of the 4th month.
how do I get it to display the nth day of the nth month?
since i also tried
$this_months_friday = strtotime('every 3 days +4 months');
and it did not return any result. Should i stick with strtotime on this one or move to DateTime function of php. though i wont still be able to formulate the proper argument for that kind of date sequence.
Any help would be greatly appreciated.
Thank You.
Probably better off using DateTime with a couple intervals:
$d = new DateTime();
$d->add(new DateInterVal('P' . $days . 'D'))->add('new DateInterVal('P' . $months . 'M'));
not sure what youre two example intervals are wanting.
You want an internval to start in 4 months, which then repeats every 3 days?
That'd be something more like
$d = new DateTime();
$d->add(new DateInterval('P4M')); // jump ahead 4 months immediately
$day3 = new DateInterval('P3D');
for ($i = 0; $i < 100; $i++) {
$d->add($day3); // jump ahead 3 days
... do something with this new date
}
for a basic recurring event, +4 months + 3 days, you'd simply have one interval:
$interval = new DateInteval('P4M3D'); // +4 months +3 days
$date = new DateTime();
while($some_condition) {
$date->add($interval);
do_something();
}
You can do this by saving the values in variables like that :
$day=3;
$month=4;
echo date("d-m-y",strtotime('+'.$day .'days' .'+'.$month.'months'));
Explanation:
7(july)+4 months = 11 month(November)
8 july+ 3 days = 11 july
Output:
11-11-13
NOTE: just for the example I have put the values hard coded, You can make them dynamic.
I would like to be able to find the date which "Sunday" falls on for a given date, formatted as YYYY-MM-DD.
... How would this be achieved in PHP?
strtotime() may help you, it accepts GNU-Date-input-formats like "next Sunday"
echo date('Y-m-d',strtotime('sunday',strtotime("2011-07-04 Z")));
Look at the time function for php.
If you can't find a library that does this, then:
Come up with a reference date (January 1, 1970?) for which you know the day of the week.
Calculate the number of days between the reference date and your given date.
Take that answer modulo 7.
Convert to a day of the week.
Here you have a full example with multiples values
it is for PHP or any other lenguage that uses epoch time (or similar)
<?php
function prevSunday($paramDay){
$aDay = 24*60*60;
$aWeek = $aDay * 7;
$sunday = $aDay + $paramDay - (($paramDay - 3 * $aDay) % $aWeek);
return $sunday;
}
$randDay = 1309819423 + rand(0, 9000000); // this contanis a random day (and hours, minutes, seconds)
$aSaterday = strtotime("20110702");
$aSunday = strtotime("20110703");
$aMonday = strtotime("20110704");
echoTwoDays($aSuterday, prevSunday($aSuterday));
echoTwoDays($aSunday, prevSunday($aSunday));
echoTwoDays($aMonday, prevSunday($aMonday));
/* echoes
day1: Saturday 20110702
day2: Sunday 20110626
day1: Sunday 20110703
day2: Sunday 20110703
day1: Monday 20110704
day2: Sunday 20110703
*/
echoTwoDays($randDay, prevSunday($randDay)); // echoes a random date and perv sunday
function echoTwoDays ($day1, $day2) {
echo "day1: " . date("l Ymd", $day1) ."<br>"; // remove l as your request
echo "day2: " . date("l Ymd", $day2) ."<br><br>"; // remove l as your request
}
function prevSunday($paramDay){
$aDay = 24*60*60;
$aWeek = $aDay * 7;
$sunday = $aDay + $paramDay - (($paramDay - 3 * $aDay) % $aWeek);
return $sunday;
}
?>
I have debugged this legacy code, and would like a sanity check on it.
The purpose of it is to allow someone to choose a delivery frequency for shipping a product. If someone wants their product Every Other Week, the system needs to determine if they should get an order next week, or two weeks from now. We call it A week, or B Week.
Keep in mind I did not write this, I am just trying to make sense of it and would like some help evaluating its accuracy:
if (date("l") == "Monday" ) {
$start = 0;
} else if (date("l") == "Tuesday" || date("l") == "Wednesday" || date("l") == "Thursday" || date("l") == "Friday" || date("l") == "Saturday"|| date("l") == "Sunday") {
$start = -1;
}
// if changing to every other week set to next week's a/b-ness
$a_week_tid = 34;
$b_week_tid = 35;
$every_other_week_frequency_id = 32;
if ($delivery_frequency == $every_other_week_frequency_id) {
$julian = (int) (strtotime('Monday +' . $start . ' week') / 86400);
$julian_week = ($julian-4) / 7;
if ($julian_week % 2) {
$today_a_or_b = $b_week_tid;
$next_week_a_or_b = $a_week_tid;
$a_or_b_week_string = '(A Week)';
} else {
$today_a_or_b = $a_week_tid;
$next_week_a_or_b = $b_week_tid;
$a_or_b_week_string = '(B Week)';
}
} else {
$next_week_a_or_b = NULL;
$a_or_b_week_string = NULL;
}
This code is not commented or documented. The part that confuses me is:
Why is 4 subtracted from Julian, then divided by 7?
If today is Monday, $julian_week is 2129, and 2129 % 2 evaluates TRUE. Is that correct?
Is this even how it should be done? Can't I rewrite this using date('w') a lot easier?
Yeah using date would totally be easier, plus it takes into account leap years, daylight saving time, all that extra stuff you don't want to have to deal with.
if (date('W')%2==1)
That's SOOOO much easier to maintain than the above.
I don't believe you can use date("W") in this case. According to the ISO calculation, on occasion, there will be years with 53 weeks. In those years, Week 53 is followed by Week 01, both odd numbers, and an A/B calculation based on Even/Odd ISO week number would result in two successive A or B weeks.
The original calculation determines the number of days from the UNIX epoch of the present Monday, or of the most recent Monday if today is not a Monday. The -4 causes the A/B week labels to change on Thursdays. Even/oddness of a week is determined from a fixed date (the Unix Epoch), so there will be no discontinuity in the oscillation of A/B-ness using the original code.
The ISO standard for week one in a year is that it is the week that the first Thursday of the year falls. This is the reason for the 4 subtracted from the Julian date. The week number is then found by dividing by 7.
Again the ISO standard implies that week number cannot be greater than 53. I don't understand how your figure of 2129 can arise. However the div operator will not evaluate TRUE for this figure. Checking the div operator on the week number is the way of determining whether you are in week a or b. If it is before Thursday, it is quite likely that the number will be 1 less than you anticipate.
The coding looks fairly good to me, though I have not stepped through all of it. It does look correct.
Using W on consecutive Fridays, mod by 2. Both lines output 1. So doing it this way will occasionally fail.
echo date('W',strtotime('2016-01-01'))%2;
echo date('W',strtotime('2016-01-08'))%2;
Just a simple way.
<?php
$weekNumber = date("W");
echo 'Week number:',$weekNumber;
if($weekNumber&1) {
echo '<strong>Week A.</strong>';
} else {
echo '<strong>Week B.</strong>';
}
?>
$day = '2019-11-10';
$date = new DateTime($day);
$dayOfMonth = $date->format("j"); // month days 1 - 30
$weekNumber = ceil($dayOfMonth / 7); // get the week number
if ($weekNumber % 2 == 0) { //if week number is even
echo "Even Week";
} else {
echo "Odd Week";
}
**// output Even Week**