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;
}
Related
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)
How can I get 48 hours excluding weekends? For example today is 2020-01-31 23:00:00, I add 48 hours it should be 2020-02-04 23:00:00 but when I tried this code:
$time = strtotime('+48 hour');
while (date('w', $time) % 6 == 0) {
$time = strtotime('+1 day', $time);
}
$date = date('Y-m-d H:i:s', $time);
It gave me 2020-02-03 23:00:00.
Welcome to stack overflow. Since PHP7 is available on many servers, you can use the comfortable date classes. The following example does exactly what you want. The classes used have been available since PHP5 (for several years).
$start = new DateTime('2020-01-31T23:00:00');
$end = (new DateTime('2020-01-31T23:00:00'))->modify('midnight +3 weekdays');
$interval = new DateInterval('PT1H');
$range = new DatePeriod($start, $interval, $end);
foreach ($range as $date) {
if ($date->format('N') == 6 || $date->format('N') == 7) {
continue;
}
var_dump($date->format('Y-m-d H:i:s'));
}
First we define a start and an end date. For this example I 've chosen last friday to demonstrate, that saturday and sunday are ignored. Don't let the three days of the week confuse you. We start at midnight on the start date to get the full two workdays including the whole start date. Since you wanted every single hour, we use the DateInterval class and define an hourly interval. With start, end and the interval we can iterate through a range with the DatePeriod class. In the loop we check, if the weekday (assuming that 6 is saturday and 7 is sunday) is saturday and sunday, the date will be modified until the next monday is reached. The output is every hour skipping the weekend.
Please have a look in the php documentation for date and time to understand what these classes can do for you and how they work. Don 't just copy this example.
I can add x week to my date
//$ultima_azione <--- 2015/07/15
//$data['intervallo'] <---- 5
$mydate = date("Y-m-d",strtotime($ultima_azione." +".$data['intervallo']." weeks"));
now how can i give a day starting from that week
example:
//$mydate + "next Monday" -----> final date
and this ve to work like, if today is Monday and i add weeks to jump to an other Monday and then i select the next Monday the week don't ve to change
The simplest way would be to use strtotime. It can do date calculations based on a textual representation of the delta:
$mydate = strtotime('+3 weeks');
It also accepts a second parameter, which is a timestamp to start from when doing the calculation, so after you get the offset in weeks, you can pass the new date to a second calculation:
// Get three weeks from 'now' (no explicit time given)
$mydate = strtotime('+3 weeks');
// Get the Monday after that.
$mydate = strtotime('next Monday', $mydate);
See strtotime documentation for more examples of notations that you can use.
I would highly recommend using PHP's built-in DateTime class for any date and time logic. It's a much better API than the older date and time functions and creates much cleaner and easier to read code.
For example:
// Current date and number of weeks to add
$date = '2015/07/15';
$weeks = 3;
// Create and modify the date.
$dateTime = DateTime::createFromFormat('Y/m/d', $date);
$dateTime->add(DateInterval::createFromDateString($weeks . ' weeks'));
$dateTime->modify('next monday');
// Output the new date.
echo $dateTime->format('Y-m-d');
References:
DateTime.
DateTime::createFromFormat
DateTime::add
DateTime::modify
DateInterval::createFromDateString
DateTime::format
Are you looking for something like this?
$today = time();
$weeks = 2;
// timestamp 2 weeks from now
$futureWeeks = strtotime("+ ".$weeks." weeks");
// the next monday after the timestamp date
$futureMonday = strtotime("next monday",$futureWeeks);
echo date("Y-m-d", $futureMonday);
// or in one line
echo date("Y-m-d", strtotime("next monday", strtotime("+ ".$weeks." weeks")));
PHP is using an unix timestamp for date calculations. Functions as date() and strtotime() using a timestamp as an optional second parameter. This is used a reference for formatting and calculations. If no timestamp is passed to the function the current timestamp is used (time()).
I have the answer here. This will show the next wednesday every 2 weeks and the first date to start from would be the 10th.
I have also added in an estimated delivery which would be 6 weeks after that date.
We will be placing our next order for this on:
<?php
$date = '2020/05/26';
$weeks = 2;
$dateTime = DateTime::createFromFormat('Y/m/d', $date);
$dateTime->add(DateInterval::createFromDateString($weeks . ' weeks'));
$dateTime->modify('wednesday');
echo $dateTime->format('d/m/Y');
?>
Expected delivery for the next order will be:
<?php
$date = '2020/05/26';
$weeks = 2;
$dateTime = DateTime::createFromFormat('Y/m/d', $date);
$dateTime->add(DateInterval::createFromDateString($weeks . ' weeks'));
$dateTime->modify('+42 days next wednesday');
echo $dateTime->format('d/m/Y');
?>
If anyone can confirm this is correct that would be great.
I'm trying to format a SQL timestamp in PHP based on the following conditions, but can't figure out how. Can anyone point me in the right direction?
If the timestamp was TODAY, display as 4:15PM or 12:30AM
If the timestamp was before TODAY but in the past 7 DAYS, list as 'Sunday' or 'Monday'
If the timestamp was before 7 DAYS ago, list as 'mm/dd/yy'
How would I go about that?
First you need to convert the MySQL time to a unix timestamp which is what most of php date functions use. If you are using MySQLs DateTime type, you can perform the conversion in SQL with the MySQL function unix_timestamp() mysql date functions. Or you can convert the mysql date to a unix timestamp in PHP with the strtotime($mysqlDateTime) function php strtotime function
once you have the unix timestamp of the time you would like to format, the conversion would look something like this (86400 is number of seconds in 24 hours):
function displayDate($timestamp)
{
$secAgo = time() - $timestamp;
// 1 day
if ($secAgo < 86400)
return date('h:i:A', $timestamp);
// 1 week
if ($secAgo < (86400 * 7))
return date('l', $timestamp);
// older than 1 week
return date('m/t/y', $timestamp);
}
This method has the benefit of not requiring extra object creation in PHP (a tad slow) or performing unnecessary calculations on the SQL server. It might also help to know that MySQL's timestamp type stores data as a unix timestamp (number of seconds since Jan 1 1970) value requiring only 32bits for storage compared to datetime which uses 64bits of storage. 32 bits should be enough for everyone, until 2038 or something....
you can check date difference by by diff() of PHP or by msql datediff()
http://www.php.net/manual/en/datetime.diff.php
Then check difference is zero or equal to 1 or greater than 7
h 12-hour format of an hour with leading zeros 01 through 12 date('H:i:s')
i Minutes with leading zeros 00 to 59
s Seconds, with leading zeros 00 through 59
G 24-hour format of an hour without leading zeros 0 through 23
USE DATE(G) to find AM or PM
if($TODAY)
date('h:i:s')PM
ELSE IF ($THISWEEK)
l (lowercase 'L') A
full textual representation of the day of the week Sunday through Saturday
ELSE IF($BEFOREONEWEEK)
date('d-m-y')
http://php.net/manual/en/function.date.php
This should work. Hope so :-)
You just have to use a conditional:
$now = new DateTime("now");
$ystrday = new DateTime("yesterday");
$weekAgo = new DateTime("now")->sub(new DateInterval('P7D'));
$inputDate = new DateTime(whenever);
if($yesterday < $inputDate and $inputDate < $now){
$outDate = date('g:ia', $inputDate->getTimestamp() );
}else if($weekAgo < $inputDate and $inputDate < $now){
$outDate = date('l', $inputDate->getTimestamp() );
}else if($inputDate < $weekAgo){
$outDate = date('d/m/y', $inputDate->getTimestamp() );
}
This hasn't been tested and you'll need to get your mySql date into a php DateTime object but it should get you pretty close.
I assume you're talking about the MySQL TIMESTAMP datatype, since I don't think MySQL actually has a datatype like a Unix timestamp (i.e. seconds since epoch), so you'll have to first convert the date you get using the strtotime function:
$timestamp = strtotime($dbTimestamp);
This will return a Unix timestamp you can play with.
Next we'll define a couple more timestamps to compare this value against:
First, we want to know the timestamp for midnight this morning. For that, you'll pass the string "today" to strtotime:
$today = strtotime("today");
Next, we need to know the timestamp for seven days ago. You'll have to choose between "1 week ago" and "1 week ago midnight". The difference between these two is that midnight will return the timestamp for 12am on that day, while the version without it will return the current time, seven days ago (e.g. today, the difference would be that midnight will return 12 AM on April 7 and the non-midnight version would, right now, return 3:45PM on April 7):
$weekAgo = strtotime("1 week ago midnight");
(Note, there are many formats that strtotime understands, including many relative formats like the "today" and "1 week ago" examples used above.)
Next, we need to define the date formats to use in each case:
$timeOnly = "g:i A"; // This gives an "hour:minute AM/PM" format, e.g. "6:42 PM"
$dayOfWeek = "l" // Gives a full-word day of the week, e.g. "Sunday"
$mdy = "m/d/Y" // gives two-digit month and day, and 4-digit year,
// separated by slashes, e.g. "04/14/2011"
Finally, we just do our comparisons, and format our timestamp using the date function:
if ($timestamp >= $today) {
$date = date($timeOnly, $timestamp);
} elseif ($timestamp >= $weekAgo) {
$date = date($dayOfWeek, $timestamp);
} else {
$date = date($mdy, $timestamp);
}
This will leave you with a string variable called $date which contains your database-provided timestamp in the appropriate format, which you can display on your page as needed.
I've seen some variants on this question but I believe this one hasn't been answered yet.
I need to get the starting date and ending date of a week, chosen by year and week number (not a date)
example:
input:
getStartAndEndDate($week, $year);
output:
$return[0] = $firstDay;
$return[1] = $lastDay;
The return value will be something like an array in which the first entry is the week starting date and the second being the ending date.
OPTIONAL: while we are at it, the date format needs to be Y-n-j (normal date format, no leading zeros.
I've tried editing existing functions that almost did what I wanted but I had no luck so far.
Using DateTime class:
function getStartAndEndDate($week, $year) {
$dto = new DateTime();
$dto->setISODate($year, $week);
$ret['week_start'] = $dto->format('Y-m-d');
$dto->modify('+6 days');
$ret['week_end'] = $dto->format('Y-m-d');
return $ret;
}
$week_array = getStartAndEndDate(52,2013);
print_r($week_array);
Returns:
Array
(
[week_start] => 2013-12-23
[week_end] => 2013-12-29
)
Explained:
Create a new DateTime object which defaults to now()
Call setISODate to change object to first day of $week of $year instead of now()
Format date as 'Y-m-d' and put in $ret['week_start']
Modify the object by adding 6 days, which will be the end of $week
Format date as 'Y-m-d' and put in $ret['week_end']
A shorter version (works in >= php5.3):
function getStartAndEndDate($week, $year) {
$dto = new DateTime();
$ret['week_start'] = $dto->setISODate($year, $week)->format('Y-m-d');
$ret['week_end'] = $dto->modify('+6 days')->format('Y-m-d');
return $ret;
}
Could be shortened with class member access on instantiation in >= php5.4.
Many years ago, I found this function:
function getStartAndEndDate($week, $year) {
$dto = new DateTime();
$dto->setISODate($year, $week);
$ret['week_start'] = $dto->format('Y-m-d');
$dto->modify('+6 days');
$ret['week_end'] = $dto->format('Y-m-d');
return $ret;
}
$week_array = getStartAndEndDate(52,2013);
print_r($week_array);
We can achieve this easily without the need for extra computations apart from those inherent to the DateTime class.
function getStartAndEndDate($year, $week)
{
return [
(new DateTime())->setISODate($year, $week)->format('Y-m-d'), //start date
(new DateTime())->setISODate($year, $week, 7)->format('Y-m-d') //end date
];
}
The setISODate() function takes three arguments: $year, $week, and $day respectively, where $day defaults to 1 - the first day of the week. We therefore pass 7 to get the exact date of the 7th day of the $week.
Slightly neater solution, using the "[year]W[week][day]" strtotime format:
function getStartAndEndDate($week, $year) {
// Adding leading zeros for weeks 1 - 9.
$date_string = $year . 'W' . sprintf('%02d', $week);
$return[0] = date('Y-n-j', strtotime($date_string));
$return[1] = date('Y-n-j', strtotime($date_string . '7'));
return $return;
}
shortest way to do it:
function week_date($week, $year){
$date = new DateTime();
return "first day of the week is ".$date->setISODate($year, $week, "1")->format('Y-m-d')
."and last day of the week is ".$date->setISODate($year, $week, "7")->format('Y-m-d');
}
echo week_date(12,2014);
You can get the specific day of week from date as bellow that I get the first and last day
$date = date_create();
// get the first day of the week
date_isodate_set($date, 2019, 1);
//convert date format and show
echo date_format($date, 'Y-m-d') . "\n";
// get the last date of the week
date_isodate_set($date, 2019, 1, 7);
//convert date format and show
echo date_format($date, 'Y-m-d') . "\n";
Output =>
2018-12-31
2019-01-06
The calculation of Roham Rafii is wrong. Here is a short solution:
// week number to timestamp (first day of week number)
function wn2ts($week, $year) {
return strtotime(sprintf('%dW%02d', $year, $week));
}
if you want the last day of the week number, you can add up 6 * 24 * 3600
This is an old question, but many of the answers posted above appear to be incorrect.
I came up with my own solution:
function getStartAndEndDate($week, $year){
$dates[0] = date("Y-m-d", strtotime($year.'W'.str_pad($week, 2, 0, STR_PAD_LEFT)));
$dates[1] = date("Y-m-d", strtotime($year.'W'.str_pad($week, 2, 0, STR_PAD_LEFT).' +6 days'));
return $dates;
}
First we need a day from that week so by knowing the week number and knowing that a week has seven days we are going to do so the
$pickADay = ($weekNo-1) * 7 + 3;
this way pickAday will be a day in our desired week.
Now because we know the year we can check which day is that.
things are simple if we only need dates newer than unix timestamp
We will get the unix timestamp for the first day of the year and add to that 24*3600*$pickADay and all is simple from here because we have it's timestamp we can know what day of the week it is and calculate the head and tail of that week accordingly.
If we want to find out the same thing of let's say 12th week of 1848 we must use another approach as we can not get the timestamp. Knowing that each year a day advances 1 weekday meaning (1st of november last year was on a sunday, this year is on a monday, exception for the leap years when it advances 2 days I believe, you can check that ). What I would do if the year is older than 1970 than make a difference between it and the needed year to know how many years are there, calculate the day of the week as my pickADay was part of 1970, shift it back one weekday for each. $shiftTimes = ($yearDifference + $numberOfLeapYears)%7, in the difference. shift the day backwords $shiftTimes, then you will know what day of the week was that day those years ago, then find the weekhead and weektail. Same thing can be used also for the future if it seems simpler. Try it if it works and tell me if it does not.
For documentation (since Google ranks this question first when searching for "php datetime start end this week").
If you need the startdate and enddate for the current week (using DateTime):
$dateTime = new DateTime('now');
$monday = clone $dateTime->modify(('Sunday' == $dateTime->format('l')) ? 'Monday last week' : 'Monday this week');
$sunday = clone $dateTime->modify('Sunday this week');
var_dump($monday->format('Y-m-d')); // e.g. 2018-06-25
var_dump($sunday->format('Y-m-d')); // e.g. 2018-07-01
Hope this will help.
The "first day of the week" is subjective. Some cultures use "Monday" others "Sunday", maybe others something else?
For my purposes, I want the first day of the week to be "Sunday" and the last day of the week to be "Saturday".
Also, using DateTime with no arguments will default to "now" which includes the current time. The following method will disregard the current time by specifying "today" in the DateTime constructor.
Furthermore the string "sunday this week" does not seem to be reliable. It actually will return Sunday the next week (according to my view of what a week is).
I've built a method which returns a PHP object containing two DateTime objects. One for the first day (Sunday) of the given week, the second for the last day (Saturday) of the given week.
function get_first_and_last_day_of_week( $year_number, $week_number ) {
// we need to specify 'today' otherwise datetime constructor uses 'now' which includes current time
$today = new DateTime( 'today' );
return (object) [
'first_day' => clone $today->setISODate( $year_number, $week_number, 0 ),
'last_day' => clone $today->setISODate( $year_number, $week_number, 6 )
];
}
Have you tried PHP relative dates? It might work.
Even if you dont want to use a specific date you cannot escape it. You can calculate a week based on the date ONLY.
Steps:
get the first day of the year
decide when the first week starts ( there are some rules that include first Thursday if I remember.
add some number of weeks (your first param). Zend_Date has an add() function where you can add weeks for example. This will give you the first day of the week.
offset and get the last day.
I would recommend working with a consistent dates sistem like Zend_Date or Pear Date.
function getStartAndEndDate($week, $year)
{
$week_start = new DateTime();
$week_start->setISODate($year,$week);
$return[0] = $week_start->format('d-M-Y');
$time = strtotime($return[0], time());
$time += 6*24*3600;
$return[1] = date('d-M-Y', $time);
return $return;
}
$dateParam = '2018-06-10';
$week = date('w', strtotime($dateParam));
$date = new DateTime($dateParam);
$firstWeek = $date->modify("-".$week." day")->format("Y-m-d H:i:s");
$endWeek = $date->modify("+6 day")->format("Y-m-d H:i:s");
echo $firstWeek."<br/>";
echo $endWeek;
will print
2018-06-10 00:00:00
2018-06-16 00:00:00
hopefully will help