Daylight savings calculation in Php - php

In my application I have varchar field in mysql for 365 days in particular format i.e. '0000-04-12' (12th of April). Right now I am having a function that should check if particular date from field falls in daylight saving zone of Calgary-Canada, which ranges from 2:00 pm Second Sunday of March to 2:00 pm First Sunday of November. and returns true or false accordingly.
<?php
/*
#param $time form Database e.g. 0000-04-12
*/
function isDaylightSaving($time){
// to replace 0000 in start with current year
$today = substr_replace($time,date('Y'),0,4);
$date = new DateTime($today);
$week = $date->format('W');
// TO DO
// find date falls between 2:00 pm Second Sunday of March to 2:00 pm First Sunday of November.
return ;
}
?>
Right now its returning the week with respect to particular year but I need to check week with respect to month to perform particular logic, which I am unable to get.Thanks.

Try this:
if($time > date('Y-m-d',strtotime('second sunday of march')) &&
$time < date('Y-m-d',strtotime('first sunday of november'))){
return true;
}else{
return false;
}
strtotime() is a great function.

The example given by #Ezenhis sounds good, but lacks of some elements.
Extending it:
$low = new DateTime('#'.strtotime('second sunday of march'));
$high = new DateTime('#'.strtotime('first sunday of november'));
if($date > $low && $date < $high) {
// we're good
}
You shouldn't compare strings from date functions. Using DateTime is also a better way to handle dates/times in PHP since PHP 5.0.

Related

Check if it is the first monday of a quarter

I want to run a script every 1st monday of a month in the windows scheduler. The script itself should check if it is the 1st monday of a quarter (not month).
I know that I can somehow do it with date() or more like the DateTime-object, but I have no idea how to approach this.
An approach I had, even though I don't think that this is very reliable or "clean", is to put the specific months in an array like
// might as well use the numeric month representation...
$quarters = array("January", "April", "July", "October");
and check if it is the first monday of a month and check afterwards, if the current month is in the array quarters. However, feels like this isn't real clean.
If the script runs, it should simply print either:
Today is the 1st monday of a quarter or do nothing. If I would run this job everyday, it should ~90 days do nothing and only once trigger with the given string. If I run it every monday, it should do 12 times nothing and also, only once, trigger.
Hope you can point me in the right direction.
There are a few stages in this solution, I've added comments as they are probably useful in the end code...
$date = new DateTime();
// Calculate start month of quarter from date
$quarterMonth = (floor(($date->format('m') - 1) / 3) * 3) + 1;
// Set date from year, start quarter month and the 1st of the month
$date->setDate($date->format('Y'), $quarterMonth, 1);
// Set result to the first Monday on or after the date
$date->modify('first monday of this month');
echo $date->format('Y-m-d');
running that will give (as of date of answer)...
2021-01-04
I would suggest building a relative date string such as first monday of january 2024 to construct the date:
$s1 = "2024-03-31";
$d1 = new DateTime($s1);
// the floor(...) expression below maps 1/2/3 to 0, 4/5/6 to 1 and so on
$yy = $d1->format("Y");
$mm = ["january", "april", "july", "october"][floor(($d1->format("n") - 1) / 3)];
$d2 = new DateTime("first monday of $mm $yy");
echo $d2->format("D Y-m-d H:i:s");
// result:
// Mon 2024-01-01 00:00:00
Old school solution with date() and strtotime():
function isFirstMondayOfQuarter($date = 'today'){
$ts = strtotime($date);
if(date('n',$ts)%3 != 1) return false;
return $ts === strtotime('first monday of this month',$ts);
}
var_dump(isFirstMondayOfQuarter()); //bool(false) at 10 Feb 2021
var_dump(isFirstMondayOfQuarter('2021-01-04')); // bool(true)

PHP Display next delivery date for twice weekly deliveries

I have a website where we show next delivery date, eg for a weekly delivery each Tuesday -- although the actual day that deliveries go out needs to be manually changed sometimes. I need to update it to (eg) Tuesday and Friday deliveries, and I'm struggling to find a good method.
Here's how I've got it set up currently:
<?php
$start_date = '2020-05-05'; // Date in the past to start counting from: YYYY-MM-DD
$date_interval = new DateInterval('P7D'); // DELIVERY EVERY x DAYS: PxD (usually P7D)
// create a DateTime object that represents start of sequence
$start_datetime = DateTime::createFromFormat('Y-m-d', $start_date);
// create a DateTime object representing the current date
$current_datetime = new DateTime('today');
// determine end date for DatePeriod object that will later be used.
// This is no further out than current date plus the interval.
$end_datetime = new DateTime('tomorrow');
$end_datetime->add($date_interval);
$date_period = new DatePeriod($start_datetime, $date_interval, $end_datetime);
// iterate until the last date in the set
foreach($date_period as $dp) {
$next_delivery = $dp;
}
echo $next_delivery->format('l, M j, Y');
?>
The dateperiod class says that it accepts ISO 8601 time periods, but as far as I can tell there's no way to set it to "next Tuesday or Friday, whichever is closer".
One hacky method I've thought of that would work is to run this function twice, once for Tuesday and once for Friday, compare with today's date, and display whichever is sooner in the future. But surely there's a more elegant way?
That's a very long winded way to find the next available Tuesday or Friday. One way to do it is check to see what day of the week it is and dynamically set the day based on that:
$day = (in_array((int) date('w'), [0,1,5,6], true)) ? 'Tuesday' : 'Friday';
echo (new DateTime("next {$day}"))->format('l, M j, Y');
output:
Tuesday, May 12, 2020
The code above checks to see if the day is Sunday, Monday, Friday, Or Saturday. If so, set the next day to "Tuesday". Otherwise, set it to "Friday". Then you can use a relative datetime value to set your date.
If you want a more human readable version of this you can spell out the days:
$day = (in_array(date('l'), ['Sunday', 'Monday', 'Friday', 'Saturday'], true)) ? 'Tuesday' : 'Friday';
It is not very difficult to find the next available Tuesday or Friday.
It is the smaller date of both.
echo min(date_create('next Tuesday'),date_create('next Friday'))->format('l, M j, Y');
Alternatively with a PHP extension for DateTime API called dt. You can find it here.
This class supports date calculations with crontab expressions. The days of the week start with 0 for Sunday. If you want to calculate the next Tuesday or Friday at 14:00 as an example, you only have to do this:
$cron = "0 14 * * 2,5"; //next Tuesday or Friday 14:00
$next_delivery = dt::create('today')->nextCron($cron); //today is 2020-05-10
echo $next_delivery->format('l, M j, Y, H:i');
//Tuesday, May 12, 2020, 14:00

PHP Recurently check if time is in a range, when the range spans more than one day

There are a lot of SO questions showing you how to check if a date-time is within a range, but there is not much to help when you want to do recurrently and the date range spans more than one day.
As an example, how do you check if its between 22:00 on a Tuesday and 07:30 on the following Thrusday? And how do you do that week in week out?
The constructor for PHP's DataTime class accepts the relative argument this xxxday, which can be used to give you the next 'xxxday' relative to the current time.
So for example, new DateTime('next friday') will give you a datetime object representing 00:00:00 on the next Friday relative to the current day. If the current day is Friday, then that is the date which will be returned.
So if you define
$end = new DateTime(next thursday 07:30);
then $end is a DateTime object representing 22:00 on the next Tuesday from the current time, or 20:00 for today if today is a Tuesday. Then you can take the interval off the end to get the start with
$start = clone $end;
$start = $end->sub(new DateInterval('P1DT9H30M'));
which gives you a DateTime object 1day, 9hours and 30 minutes prior to 07:30 on the next Thursday from the current time, or 22:00 on the Tuesday before the next Thursday from the current time.
Then you can get the current date time and see if its between the start and end date times:
$now = new DateTime();
if( $now >= $start && $now <= $end ) {
//In interval
}

PHP: get next date based on fixed base date

is there a way in PHP to get the next date(s) using a 4-week interval from a given date ?
Example:
My start date is Friday, Jan 03, 2014 and my interval is every 4 weeks from that date.
What I am looking for is the next date (or dates, if possible) from the current date that matches this 4-week interval.
In the above example this would be Friday, May 23, 2014 (then June 20, 2014, July 18, 2014 etc.).
I know I can get the current date as follows: $today = date('Y-m-d');
and I could probably set the start date like this: $start = date('2014-01-03');
but I don't know how to calculate the interval and how to find out the next matching date(s).
You should read up on the DateTime classes, specifically DatePeriod and DateInterval:
$start = new DateTime('2014-01-03');
$interval = DateInterval::createFromDateString('4 weeks');
$end = new DateTime('2015-12-31');
$occurrences = new DatePeriod($start, $interval, $end);
foreach ($occurrences as $occurrence) {
echo $occurrence->format('Y-m-d') . PHP_EOL;
}
DatePeriod takes a start date and a DateInterval and allows you traverse over the object to get all dates within the boundaries using the given interval. The cut off can be either a set number of cycles (so the next 10 dates) or an end date (like above), even if the end date is not one of the dates the interval falls on (it will stop below it). Or you can use an 8601 interval notation string (which sounds so much fun, huh?), but I'm pretty shaky on that.
If 4-week interval means 7 x 4 = 28 days, you can obtain the "next date" by:
$today = new DateTime();
$next_date = $today->add(new DateInterval('P28D'));
$next_next_date = $next_date->add(new DateInterval('P28D'));
$next_next_next_date = $next_next_date->add(new DateInterval('P28D'));
And if you want to calculate more "next dates", you can repeat the add() to repetitively add 28 days to your date.
Note: Beside using P28D, you can use P4W, which means 4 weeks.
While some answers may suggest using strtotime(), I find the object-oriented approach more structured. However, DateInterval is only available after PHP >= 5.3.0 (while DateTime is available after PHP >= 5.2.0)
You could use strtotime()
echo date('Y-m-d', strtotime('now +4 weeks'));
UPDATED:
$start = date('Y-m-d', strtotime('2014-01-03 +4 weeks'));
echo $start;
You could also run this in a for loop to get the next 6 or more dates. For example:
$Date = "2014-01-03";
$Int = 6;
for($i=0; $i<$Int; $i++){
$Date = date('Y-m-d', strtotime('{$Date} +4 weeks'));
echo $Date;
}

Find day light saving time for a given year using php

i would like to know is there a anyway we can find the DST(day light saving time) for the given year.
For the United States daylight savings time begins the Second Sunday of March and ends on the First Sunday of November. So...
<?php
$remove_hour = strtotime("Second Sunday March 0");
$add_hour = strtotime("First Sunday November 0");
$time = time();
if( $time >= $remove_hour && $time < $add_hour )
{
var_dump("Lost an hour");
}
else
{
var_dump("Gained an hour");
}
?>
Although as far as I know this doesn't change every year? Not sure what you mean by that?
You can use the I parameter in the standard date function to get a 0/1 flag if DST.
PHP Manual Date

Categories