How can I get specific dates from a number of weeks? - php

Using PHP, I'd like to get the dates for specific weekdays within a given number of weeks. For example, I want to get the dates for Monday, Wednesday and Friday from 10 weeks.
The pseudo code for what I want is like this:
function (monday, wednesday, friday, 10) {
// 10 is week numbers
week1 5,7,9 oct 2015
week2 12,14,16 oct 2015
...
week10
}
i write a solution for this. Thanks for all answers.
<?
$dates = array();
$i = 0;
while(true) {
$i++;
$time = strtotime("+$i days");
$dayOfWeek = date('w', $time);
if(
/*
0-sun
1-mon***
2-tue
3-wed***
4-thu
5-fri***
6-sat
*/
($dayOfWeek == 0) or
($dayOfWeek == 2) or
($dayOfWeek == 4) or
($dayOfWeek == 6)
) {
continue;
}
$dates[] = date('Y-m-d', $time);
if( count($dates) > 30 ) {
break;
}
echo json_encode($dates );
}
?>

Sounds like you want to work with schedules. I suggest you to have a look at library called When, it's "Date / Calendar recursion library for PHP 5.3+".
What you want to do is MWF schedule for next 10 weeks:
$now = new DateTime('NOW');
$after10Weeks = clone $now;
$after10Weeks->modify('+10 week');
$r = new When();
$r->startDate($now)
->freq("weekly")
->until($after10Weeks)
->byday(array('MO', 'WE', 'FR'))
->generateOccurrences();
$occurrences = $r->occurrences;

Use PHP DateTime ISO date:
$date = new DateTime(); //The object
$year=2015; // Desired year
$days = array('Mon', 'Wed', 'Fri'); // Desired days of week
for ($yearDay=1; $yearDay<=366; $yearDay++) {
$date->setISODate($year,null, $yearDay); // call ISO Date
$week=$date->format('W'); // Get the week resulted
$day=$date->format('D'); // Get the day name resulted
if($week==10 && in_array($day, $days)) // return only dates of desired days of week 10
echo $date->format('M d Y')."<br>";
}
More information about ISO Date here
You can try this code with PHPTester

Related

How can I make date("W") start in Sunday and end on saturday? [duplicate]

I need to get week number in php where week should be calculated from sunday. By default its from monday. Please help me to find a way how to get week number considering sunday as starting day.
In php manual
ISO-8601 week number of year, weeks starting on Monday (added in PHP 4.1.0)
But I need to get week number of year, weeks starting on sunday.
thanks
Try this:
$week = intval(date('W'));
if (date('w') == 0) { // 0 = Sunday
$week++;
}
echo $week;
Not sure if the logic is right though;
The first solution is not correct on Jan 01, 2017 or any year that begins on a Sunday.
Try this:
$date = date('Y-m-d');
echo strftime("%U", strtotime($date ) );
To expand on silkfire answer and allow for it wrapping around years
if($date->format('w') == 0){
if(date('W',strtotime($date->format('Y')."-12-31"))==52 and $date->format('W') == 52){
$week = 1;
}
elseif(date('W',strtotime($date->format('Y')."-12-31"))==53 and $date->format('W') == 53){
$week = 1;
}
else{
$week++;
}
}
Try this one. to get sunday day must -1 day.
$date = "2015-05-25";
echo date("W", strtotime("-1 day",strtotime($date)));
You should try with strftime
$week_start = new DateTime();
$week = strftime("%U"); //this gets you the week number starting Sunday
$week_start->setISODate(2012,$week,0); //return the first day of the week with offset 0
echo $week_start -> format('d-M-Y'); //and just prints with formatting
I solved this like this:
function getWeekOfYear( DateTime $date ) {
$dayOfweek = intval( $date->format('w') );
if( $dayOfweek == 0 ) {
$date->add(new DateInterval('P1D'));
}
$weekOfYear = intval( $date->format('W') );
return $weekOfYear;
}
I know this topic is old, but this is a shorter way to do it with elvis operator and "+7 day" expression for strtotime():
$week=date("W",strtotime(date("w")==1?"+7 day":"+0 day"));
if $date("w") returns true means today is a day between tuesday and sunday (1-6), so, we can return today week ('today').
if returns false, it means is monday (0), so, we should return the next day ('+1 week').
This way we don't need to care about last or first day of year or check if current year has 52 or 53 weeks.
Edited: the previous answer (and others in this topic) doesn't work for this year because januray 1st is monday, so, it needs to be 1 week ago (-1 week) excluding sunday (day 6).
date("W",strtotime(date("w")?'-7 day':'+0 day'));
I think a condition asking if januray 1st is monday could work, but I didn't test it yet, I will come back with an answer later
For a custom day you could use this:
$date = strtotime('2018-04-30'); // (it is monday)
if(date("w",strtotime(date('Y',$date).'-01-01'))==1){ // if first day of year is monday
$week = strtotime(date('w',$date)?"-7 day":"+0 day",$date); // and today is sunday, sub a week
$week = date("W",$week);
}else{ // if is not monday
$week = strtotime(date('w',$date)==1?"+7 day":"+0 day",$date); // and today is monday, add a week
$week = date("W",$week);
}
Building on #silkfire's answer:
$year = date('Y');
$week_no = date('W');
if (date('w') == 0) { // 0 = Sunday
$week_no++;
}
// We shifted the week but the week still starts on a Monday.
$weekStartDate = new DateTime();
$weekStartDate->setISODate($year,$week_no);
// Shift start date to Sunday
$weekStartDate->add(DateInterval::createFromDateString('-1 day'));
Tested in php 5.6 Debian 7
function getWeekNumber(\DateTime $_date)
{
$week = intval($_date->format('W'));
if(intval($_date->format('w')) == 0) {
$week = intval($_date->format('W')) == ( 52 + intval($_date->format('L')) ) ? 1 : $week + 1;
}
return $week;
}
I needed to ADD day instead of subtracting to get Alghi Fari's answer to work.
$date = "2022-11-13";
echo date("W", strtotime("+1 day",strtotime($date)));

How to save date and day into separate array without sundays?

I am trying to save a series of five dates into an array to be called. The date has no range since it is taking the current date to start with.
I would like to save without any Sundays as delivery is not an option for Sunday in my case. I am saving both dates and day in separate arrays.
$date = new DateTime("+ 1 day", new DateTimeZone('Asia/Thailand') );
for ($i=1; $i<=5; $i++) {
$date->modify("+1 weekday");
$delivery_dates[] = $date->format("m/d/Y");
$delivery_days[] = $date->format("l, d F Y");
}
At the moment, I am getting the following -
Sunday, Monday, Tuesday, Wednesday, Thursday (inclusive of the dates for each day in d F Y format)
Is there a way I can get the following -
Monday, Tuesday, Wednesday, Thursday, Friday (inclusive of the dates for each day in d F Y format)?
For every Sunday I would like to +1 day so it makes an available day for delivery, on Monday.
I have used the following -
for ($i=1; $i<=5; $i++) {
$date->modify("+1 weekday");
if ($date->format("N") !== 7 {
$delivery_dates[] = $date->format("m/d/Y");
$delivery_days[] = $date->format("l, d F Y");
}
}
The codes above still display Sunday.
$from = '2018-10-10';
$to = '2018-12-10';
$start = new \DateTime($from);
$end = new \DateTime($to);
$interval = \DateInterval::createFromDateString('1 day'); // 1 day === P1D, 5 month and 5 years === P5M5Y
$period = new \DatePeriod($start, $interval, $end); // A date period allows iteration over a set of dates and times, recurring at regular intervals, over a given period.
// new \DatePeriod(10-10-2010, 5, 30-10-2010) ===> [10-10-2010, 15-10-2010, 20-10-2010, 25-10-2010, 30-10-2010]
$result = [];
foreach ($period as $day) {
if (! in_array($day->format('w'), [0, 6])) { // check every date in period, ->format('w'): w - number of day; Monday = 1 or 7 (depends on wat day declared first)
$result['date'][] = $day->format("m/d/Y");
$result['day'][] = $day->format("l, d F Y");
}
}
Assuming you can use Carbon, one way to implement is to generate the range with the help of a while-loop, and only add a date if it is not a Sunday, while ensuring that you'll get the required amount of days, in your case, 5.
/**
* #param int $amount
* #return Carbon[]
*/
public function getDeliveryDates($amount = 5): array
{
$days = [];
$current = Carbon::today();
while (\count($days) < $amount) {
$day = clone $current; // addDay works on instance, cloning it
$day->addDay();
$current = $day; // setting current to current day, so that it will iterate
if ($current->isSunday()) {
continue;
}
$days[] = $current;
}
return $days;
}
Then you can just format your date. If you still want two arrays with the info, you just need to iterate over the generated array:
$formattedDates = [];
$formattedDays = [];
foreach (getDeliveryDates() as $date) {
$formattedDates[] = $date->format('m/d/Y');
$formattedDays[] = $date->format('l, d F Y');
}

Alter date if it's a weekend date PHP

I have user defined date that I add one week to. I am trying to check the user's date and see if it's a Friday,Saturday,Sunday or Monday. If it is, then I want to loop until the date is a day other than those days (pseudo code below). The code I have doesn't actually seem to work.
$date = 10/10/2012;
while (date = friday, saturday, sunday, monday) {
$date = $date - 1;
}
Here is my code:
$postpone = date('Y-m-d', strtotime('+1 Week'));
$checkDate = date('w', strtotime($postpone));
while ($checkDate == 0 || $checkDate == 6 || $checkDate == 5 || $checkDate == 1) {
$postpone = date_sub($postpone,date_interval_create_from_date_string("1 day"));
$postpone = date("Y-m-d", $postpone);
$checkDate = date('w', strtotime($postpone));
}
Below code uses the object-oriented PHP methods to accomplish this. Note that it increments the date by 1 day and you can add or subtract any interval depending on how you want to reach your target weekday.
// Make sure to set timezone when using PHP DateTime
date_default_timezone_set('UTC');
// Create a new date set to today's date
$date = new DateTime;
// Add 1 week to the date
$date->add(new DateInterval('P1W'));
// Get a numeric representation of weekday for date (0-6 0=Sunday)
$weekday = $date->format('w');
// Loop while weekday is Fri, Sat, Sun, Mon
while ($weekday > 4 || $weekday < 2) {
// Add one day to date and get the weekday
$weekday = $date->add(new DateInterval('P1D'))->format('w');
}
echo $date->format('Y-m-d: w');

PHP: getting weekdays numbers of a given month

Given a Month and a weekday, I need to build a function that can retrieve the day number of all Mondays, Tuesdays, Wednesdays, Thursdays and Fridays.
Let's say I give the function this month, September 2012 and weekday number 1. The function should retrieve all the Mondays in September 2012 which are: 3, 10, 17 and 24
Please note that to me weekday number 1 is Monday, number 2 Tuesday, 3 is Wednesday, 4 Thursday and 5 Friday.
So far I've have done: getting the first day of the week given today's date (I post the function below). But I don't know how to follow from here in a simple way, I've been many hours on it and I suspect there's a better way to do it. Can you please show me how?
function getFirstDayOfWeek($date) {
$getdate = getdate($date);
// How many days ahead monday are we?
switch ( $getdate['wday'] ) {
case 0: // we are on sunday
$days = 6;
break;
default: // any other day
$days = $getdate['wday']-1;
break;
}
$seconds = $days*24*60*60;
$monday = date($getdate[0])-$seconds;
return $monday;
}
Thanks a ton
Not very smart, but would works for you:
// sept. 2012
$month = 9;
// loop through month days
for ($i = 1; $i <= 31; $i++) {
// given month timestamp
$timestamp = mktime(0, 0, 0, $month, $i, 2012);
// to be sure we have not gone to the next month
if (date("n", $timestamp) == $month) {
// current day in the loop
$day = date("N", $timestamp);
// if this is between 1 to 5, weekdays, 1 = Monday, 5 = Friday
if ($day == 1 OR $day <= 5) {
// write it down now
$days[$day][] = date("j", $timestamp);
}
}
}
// to see if it works :)
print_r($days);

PHP create range of dates

Starting with a date in this format: 2011-05-01 09:00:00, how can I create an array that contains all office hours (09:00 to 17:00) for all working days of the year (so excluding all Saturday and Sundays). What I want to arrive to is something like this:
2011-05-01 09:00:00
2011-05-01 10:00:00
2011-05-01 11:00:00
2011-05-01 12:00:00
2011-05-01 13:00:00
2011-05-01 14:00:00
2011-05-01 15:00:00
2011-05-01 16:00:00
2011-05-01 17:00:00
//next day, starting at 09:00 and ending at 17:00
2011-05-02 09:00:00
...
2011-05-02 17:00:00
//until the last day of the year from 09:00 to 17:00
2011-12-31 09:00:00
...
2011-12-31 17:00:00
The start date will be the first of the current month at with 09:00 as time and the very last date (last element of the array) will always be 17:00 on the last day of the year.
Again, weekends should be excluded.
Pseudocode idea:
I thought of something like strtotime($start, "+1 one hour") with a check for "if smaller than 17:00" but it doesn't seem to be that simple.
How about this:
$start = strtotime('2011-05-01');
$end = strtotime('2011-12-31');
$times = array();
for ($i = $start; $i <= $end; $i += 24 * 3600)
{
if (date("D", $i) == "Sun" || date("D", $i) == "Sat")
{
continue;
}
for ($j = 9; $j <= 17; $j++)
{
$times []= date("Y-m-d $j:00:00", $i);
}
}
The outer loop iterates through all the days in the given time period. In the outer loop, we check to see if the day is either Saturday or Sunday (a weekend), and if it is, we skip that day. If it's not a weekend, we loop through all the valid hours, adding the full date and time to the array as we go.
Some tips:
date("G", $some_timestamp) gives you the hour of the day in 24-hour format
date("N", $some_timestamp) gives you the day of the week, 1 (for Monday) through 7 (for Sunday)
Take a look at the php manual for date.
Edit: You can pick any start timestamp and add 3600 to add one hour, if your hour is greater than 17, you can add a bigger step to go right to the next morning, same for a weekend, and just do a while ($timestamp < $end_timestamp) {}
I'd encourage you to use the wonderful DateTime class and its related classes. Here, you can make good use of DatePeriod:
<?php
$now = new DateTime('today'); // starting time 0.00 this morning
$endOfYear = new DateTime('31 December this year 23:00'); // end time
$interval = new DateInterval('PT1H'); // frequency -- every hour
$times = array();
foreach (new DatePeriod($now, $interval, $endOfYear ) as $datetime) {
// $datetime is a DateTime object for the hour and time in question
$dow = $datetime->format('w'); // 0 is Sunday
if (($dow == '0') || ($dow == '6')) {
continue; // miss Saturday and Sunday out
}
$time = $datetime->format('G'); // hour without leading 0
if (($time < '9') || ($time > '17')) {
continue;
}
$times[] = $datetime->format('r'); // output format
}
var_dump($times);
Obviously there are various aspects of this that you can configure, especially the output format. Depending on your purpose, you may prefer to put the DateTime objects themselves into the array.
$datetime = new DateTime(); // Set your start date here
do { // Iterate over .. dont know, a long time?
do { // Iterate over the week ...
$datetime->setTime(9,0,0);
do { // Iterate over the hours ...
echo $datetime->format('c') . PHP_EOL; // Do something with $datetime here
$datetime->add(new DateInterval('PT1H'));
} while ($datetime->format('G') < 18); // .. till < 18
$datetime->add(new DateInterval('P1D')); // next day
} while (!in_array($datetime->format('w'), array('0','6'))); // until we hit sunday or saturday
$datetime->add(new DateInterval('P2D')); // next monday
} while (true); // replace with your "end" expression
Currently untested.
You can use the common interval-strings (like 1 hour and so on) too http://php.net/dateinterval.createfromdatestring
You could calculate your dates with two nested loops and generate the string with date().
I would just loop through all dates, incremented by hour, from now until the end of the year, as follows (pseudocode, obviously):
for n = now until end of year
if (date(n) is between 9:00 and 17:00) AND (if date(n) is not sat or sun)
add to array
end if
increment n by 1 hour
end
Here is a solution which should be reasonably fast since it uses no string comparisons and has only two function calls inside the loops:
function hours()
{
$start = mktime(0, 0, 0, date('n'), 1, date('Y'));
$end = mktime(0, 0, 0, 1, 1, date('Y') + 1);
$wday = date('w', $start);
$result = array();
for ($t = $start; $t < $end; $t += 3600 * 24) {
if (($wday > 0) && ($wday < 6)) {
for ($hour = 9; $hour <= 17; $hour++) {
$result[] = date('Y-m-d', $t) . sprintf(' %02d:00:00', $hour);
}
}
$wday = ($wday + 1) % 7;
}
return $result;
}

Categories