Determine week number based on starting date - php

I need help to create a function to determine the week number based on these 2 parameters:
Starting date
Specified date
For example, if I specify April 7, 2010 as the starting date & passed April 20, 2010 as the date to lookup, I would like the function to return WEEK 2. Another example, if I set March 6, 2010 as starting date and looked up April 5, 2010 then it should return WEEK 6.
I appreciate your time and help.
=================
UPDATE
For instance:
Starting date: 3/6 - week1
Lookup date: 4/5
Week 2 starts from Mar 7-13.
Week 3 (3/14-3/20).
Week 4 (3/21-3/27). Week 5 (3/28-4/3).
So 4/5 falls under Week 6.
An idea is to use the Sunday of the starting date as the NEW* starting date. So instead of looking up 3/6, the function will use 2/28 as the starting date.

You can find the number of days between the two dates, divide that number by 7 and take the ceil of the result:
$start_date = strtotime("2010-04-07");
$specified_date = strtotime("2010-04-20");
$num_of_days = ($specified_date - $start_date)/(60*60*24);
$week_num = ceil($num_of_days/7);
echo $week_num; // prints 2.

What about?
Determine the number of days since the epoch of the start date
ditto, the specified date
subtract
divide by 7

Since I do not know how you are going to receive your dates, I would do something like:
$starting = mktime(parsedStartingDate);
$lookup = mktime(parsedLookupDate);
$result = $lookup - $starting;
$result = (((($result / 60) / 60) / 24) / 7);
return $result;

Since you're not being very clear this may or may not be what you're looking for:
// Example 1 (returns 2)
date('W', strtotime('April 20, 2010')) - date('W', strtotime('April 7, 2010'));
// Example 2 (returns 5)
date('W', strtotime('April 5, 2010')) - date('W', strtotime('March 6, 2010'));

Figured it out.
$start_date = strtotime("2010-03-06"); // returns 1267862400
$start_date_week = strtotime("last sunday",$start_date); // 02-28
$specified_date = strtotime("2010-04-10"); // returns 1270882800
$specified_date_week = strtotime("next sunday",$specified_date); // 4-11 looking up the Next Sunday was also the key!
$num_of_days = ($specified_date_week - $start_date_week)/(60*60*24); // 41.958
$week_num = ceil($num_of_days/7); //6
echo $week_num;

Related

PHP, repeating events check next one with unix timestamps

I have a problem with php that i don't really know how to solve. I have an array full of unix timestamps coming from a mysql query.
These timestamps are events that repeat every week ( For example, every Tuesday and Thursday ). They can repeat various days or just one.
Knowing the days that repeat, which day will be the next one.
For example:
In the Array I have :
1595289600 --> 2020/07/21 (Tuesday)
1595116800 --> 2020/07/19 (Sunday)
Today we are at 1595376000 (Wednesday) , so it should return 1595116800 + 604800 (Sunday).
In 5 days ( next monday) it should return 1595289600 + 604800 = 1595721600 (First tuesday + one week )
in one week (next Wednesday) , it should return the next Sunday (2020/08/02 ): 1596326400
And so on...
Thank you!
For every timestamp you have - calculate next timestamp (add a week) until it is after current timestamp. Then return lowest from those as that one will be the closest to now (but also in the future).
So lets say it is 2020-07-22 Wednesday.
Your 2020-07-21 Tuesday is in the past, so add a week: 2020-07-28 Tuesday - its in the future, so its our candidate.
Your 2020-07-19 Sunday is also in the past, so add a week: 2020-07-26 Sunday - its in the future so its out second candidate.
Now pick lower from 2 candidates: 2020-07-26 Sunday.
If the dates are more in the past then you will need more a week to them more times.
Something like this:
<?php
// those are your timestamps: $timestamps = [1595289600, 1595116800];
// $time is optional int for when you want to perform the calculation. defaults to current timestamp
function nextOccurence(array $timestamps, $time = null) {
$now = $time ?? time();
$nextTimestamps = [];
foreach ($timestamps as $timestamp) {
while ($timestamp < $now) {
$timestamp += 604800;
}
$nextTimestamps[] = $timestamp;
}
return min($nextTimestamps);
}

Carbon get interested week in two weeks range date

I'm trying to write an algorithm which calculate the week (saturday to saturday) of interest based on a range of date.
For example I have this range:
2018-01-04 to 2018-01-13
In this case I have two weeks of interest, it is: "week 1" From 01 to 07 of January and "week 2" From 08 to 14 of the same January.
In this case the algorithm will respond to me that the week of interest is the "Week 2" because the number of days in that week is higher than the number of days in the "week 1".
How can I do this in Carbon?
Assuming you have the start and end date as Carbon objects $s and $e
make sure the difference is less than 14 days
calculate the overlaps:
$s->diffInDays($s->copy()->startOfWeek()) "offset" into first week
$e->copy()->endOfWeek()->diffInDays($e) "remainder" of last week
if $offset > $remainder select $e; else select $s
output $selectedWeek->copy()->startOfWeek() and $selectedWeek->copy()->endOfWeek()
Apparently, startOfWeek() and endOfWeek() alter the object; so make sure to copy() before using these methods!
Implementation:
$s = new Carbon\Carbon('2018-01-04');
$e = new Carbon\Carbon('2018-01-13');
$diff = $e->diffInDays($s);
if ($diff > 14) die("uh-oh!");
$offset = $s->diffInDays($s->copy()->startOfWeek());
$remainder = $e->copy()->endOfWeek()->diffInDays($e);
$selectedWeek = ($offset > $remainder ? $e : $s)->copy()->startOfWeek();
echo "selected week {$selectedWeek->weekOfYear} ({$selectedWeek} - {$selectedWeek->copy()->endOfWeek()})";
Output:
selected week 2 (2018-01-08 00:00:00 - 2018-01-14 23:59:59)
I guess you could do something like this. I haven't tested it but you can get some idea. Also I would like to point to the documentation https://carbon.nesbot.com/docs/
// Create dates
$date1 = Carbon::create(2018, 1, 4, 0, 0, 0);
$date2 = Carbon::create(2018, 1, 13, 0, 0, 0);
// Get The week numbers
$week_date_1 = $date1->weekOfYear;
$week_date_2 = $date2->weekOfYear;
// Count number of days for each week
$number_of_days_week_1 = $date1->diffInDays($date1->startOfWeek);
$number_of_days_week_2 = $date2->diffInDays($date2->startOfWeek);
// Highest number of days per week wins
if($number_of_days_week_1 > $number_of_days_week_2){
return $week_date_1;
} else {
return $week_date_2;
}

Find the Christian Liturgical Year - Return a letter A, B, or C for any Year

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.

How do I get next occurrence of a certain day of the month

I am trying to get stripe to set a end_trial date on the next occurrence of whatever day of the month the user chooses. i.e. If today is the 16th and the user chooses the 15th I need the unix timestamp for the 15th of the next month. However if today was the 14th I need the timestamp for tomorrow.
I tried the solution found on this SO question Find the date for next 15th using php .
When i ran the code suggested in that question and substituted 15 for 31
$nextnth = mktime(0, 0, 0, date('n') + (date('j') >= 31), 31);
echo date('Y-m-d', $nextnth);
The result is 2013-03-03
I also tried this one Get the date of the next occurrence of the 18th .
The second one would actually give me 2013-03-31 when i ran it one 2013-1-31.
Both had unexpected results. Is february the problem? Any guidance will be much appreciated.
Here is a way to do it.
function nextDate($userDay){
$today = date('d'); // today
$target = date('Y-m-'.$userDay); // target day
if($today <= $userDay){
$return = strtotime($target);
}
else{
$thisMonth = date('m') + 1;
$thisYear = date('Y');
if($userDay >= 28 && $thisMonth == 2){
$userDay = 28;
}
while(!checkdate($thisMonth,$userDay,$thisYear)){
$thisMonth++;
if($thisMonth == 13){
$thisMonth = 1;
$thisYear++;
}
}
$return = strtotime($thisYear.'-'.$thisMonth.'-'.$userDay);
}
return $return;
}
// usage
echo date('Y-m-d',nextDate(29));
We get the user's choice and compare it today.
If today is less than or equal to user choice, we return the timestamp for this month.
If today is greater than user choice, we loop through dates, adding a month (or a year if it's $thisMonth hits 13). Once this date does exist again, we have our answer.
We check the dates using php's checkdate function, strtotime and date.
I really don't understand the question completely. You can easily determine the date for next 30 days for example
$next_ts = time() + 30 * 86400; // add 30 days to current timestamp
$next = date('Y-m-d', $next_ts); // format string as Y-m-d
echo $next;
If that is not what you need, please explain the problem.

Calculating amount of months between dates

How would you go about calculating the amount of months between two arbitrary dates? Given that even if just one day falls on a month, it is considered a full month.
Examples:
2010-01-01 - 2010-03-31 = three months
2010-06-15 - 2010-09-01 = four months
Et cetera. I thought of just dividing the difference of timestamps with 2592000 (average number of seconds in a month) but that seems hacky and prone to errors. And I'd like to keep it as fast as possible (needs to run thousands of times quick), so I guess using strtotime isn't optimal either?
If I am reading your question correctly, you would want to return "2" for January 31st and February 1st, because it spans both January and February, even though they are only 1 day apart.
You could work out (psuedocode):
monthno1 = (date1_year * 12) + date1_month;
monthno2 = (date2_year * 12) + date2_month;
return (monthno2 - monthno1) + 1;
This assumes that the second date is the later date.
Assuming the dates are in a known format:
function getMonths($start, $end) {
$startParsed = date_parse_from_format('Y-m-d', $start);
$startMonth = $startParsed['month'];
$startYear = $startParsed['year'];
$endParsed = date_parse_from_format('Y-m-d', $end);
$endMonth = $endParsed['month'];
$endYear = $endParsed['year'];
return ($endYear - $startYear) * 12 + ($endMonth - $startMonth) + 1;
}
This gives:
print(getMonths('2010-01-01', '2010-03-31')); // 3
print(getMonths('2010-06-15', '2010-09-01')); // 4

Categories