I have a date range that comes from MySQL, for example:
2016-01-05 to 2016-01-10. I would like to check if both Saturday and Sunday are inside that date-range, not necessarily consecutive. So far I have found:
function isWeekend($date) {
return (date('N', strtotime($date)) >= 6);
}
So I would have to loop for every single day in the range to see if it's a weekend day.
Are there any better approaches?
You don't need to loop over all the days. You just need to know the length of the date range and the first day's day of the week.
Assuming you have two DateTime objects:
$start = new DateTime('2016-01-05');
$end = new DateTime('2016-01-10');
You can determine if a Saturday and Sunday are contained in the date range by checking if the length of the range plus the numeric weekday of the start date is greater than 6.
function includes_weekend (DateTime $start, DateTime $end) {
return $start->diff($end)->format('%a') + $start->format('w') > 6;
}
format('%a') returns the total number of days in the DateInterval returned by diff, and format('w') returns the numeric day of the week (Sunday = 0).
You would not have to check every single day.
I'll try to explain this with just plain English:
First, check if it starts on a weekend. If it does, you're already done. If the date span is more than 6 days, then you can immediately assume that yes, a weekend day is included. If it's 5 days, then the first day has to be on a Monday, otherwise it contains a weekend day. If it's four, it has to be on a Tuesday... and so on.
Related
I'm trying to group together dates into a week number and year, and then I want to convert that week number back into a unix timestamp. How can I go about doing this?
I assume you are using ISO 8601 week numbers, and want the first day of a ISO 8601 week so that e.g. Week 1 of 2011 returns January 3 2011.
strtotime can do this out of the box using the {YYYY}W{WW} format:
echo date("Y-m-d", strtotime("2011W01")); // 2011-01-03
Note that the week number needs to be two digits.
Shamefully, DateTime::createFromFormat, the fancy new PHP 5 way of dealing with dates, seems unable to parse this kind of information - it doesn't have a "week" placeholder.
$week: The week number
$year: The year number
Then:
$timestamp = gmmktime (0, 0 , 0 , 1, , 4 + 7*($week - 1), $year);
The 4 + 7*($week - 1) comes from the fact that according to ISO 8601, the first week of the year is the one that contains January 4th.
strtotime('1/1/2011 + 4 weeks') (1/1 ist always in week number one; this would bring me to week number five). if you want any timestamp in the week then that's all you need, else you would have to go to the monday in this week:
$t = strtotime('1/1/2011 + 4 weeks');
$t -= 24 * 60 * 60 * date('w', $t);
Update: Instead of 1/1/2011 use the first monday in 2011. The 2nd calculation is not needed anymore.
Is there any way to get the full date from a string that does not actually contain the month?
i am given the date in a format of Wednesday 16th and need to add this to my database with a month,
The application i am making is for lifestyle couriers and they get their manifests in that format and have the last 2 months available, so i need to find out the month?
Assuming that you want to regard the current and the last two months, I can imagine, that there will be no two day numbers of the same week day in that timespan (that should be proven first).
I would iterate back over the last n days using PHP's date function and try to detect your "Wednesday 16th" where n is the aggregate of month days that date with param "t" returns for the current and the last two months.
If you have your match then, you know the month and the year (the year could be the previous year as well if you start in January or February).
You can do it like this:
<?php
$date = 16;
$day = "Wednesday";
$oneMonthAgo = explode(" ",date("m Y F",strtotime("-1 month")));
$twoMonthsAgo = explode(" ",date("m Y F",strtotime("-2 months")));
if (date("l",strtotime($date."-".$oneMonthAgo[0]."-".$oneMonthAgo[1]))==$day) {
echo "Last month: ".$oneMonthAgo[2];
}
else if (date("l",strtotime($date."-".$twoMonthsAgo[0]."-".$twoMonthsAgo[1]))==$day) {
echo "Month before last: ".$twoMonthsAgo[2];
}
else {
echo "Not valid";
}
?>
Explanation
Because you are using PHP, there is an easy way to do this. In other languages, you would have to use a weekday algorithm.
In PHP, we can convert a properly formatted string into a time, from which we can then derive date information. Examples of a properly formatted string is -1 month or -2 months, which return time objects for the previous month or the month before that, respectively.
Using the date() function, we can get the month, year and textual month values for those months. We delimiter these by a space, so that we can explode these values into an array after they are found. Thus, we now have two arrays, $oneMonthAgo and $twoMonthsAgo, which both contain their month's respective number, year and textual month at the 0, 1 and 2 indexes respectively.
Now, we can create another time, by appending the date that we are looking for ($date) onto these values, with the proper delimiters in-between (when using - as the delimiters, PHP assumes a d-m-Y format, when using / PHP assumes a m-d-Y format). Then, by passing that through another date() function, we can find the data that we are looking for: the textual day that took place at that date. Now we can simply compare that to the day that we are looking for, $day. If the textual day is the same, then this is the month which we are looking for, so we can print out the full textual month.
We do this in an if / else statement for both months, and if we still haven't found it, assume that the date is invalid.
Notes
References to the PHP functions used can be found on the PHP Manual: date() function, strtotime() function, Valid dates for strtotime()
Yes and no. Since full date requires month to be known you need to know what to do with lack of that information. If you "guess" the month (be it current one or random, does not matter), then "yes" is close. If you cannot tell what the month we talk about then answer is no (or random).
PS: you may need a year too...
I use a while loop to loop backwards however many months needed to find what is searched for.
$date = 16;
$day = "Wednesday";
$x=0;
$start = date("Y-m-") . $date;
While(date("l", strtotime($start ."-" .$x . "months")) != $day){
$x++;
}
Echo $x . " months ago.";
// Or to output the date:
//Echo date("Y-m-d", strtotime($start ."-" .$x . "months"));
https://3v4l.org/vUYeX
This will output 0 months ago.
But if input $date= 15; it will output 5 months ago (March 2017).
I'm looking for functionality that would do the opposite of
strtotime("third monday");
i.e. a function that is fed a timestamp and would return the weekday number of the month.
So if today is 18.07.2016, ideally the function should return "3" (i.e. 3rd Monday of July).
I can get the weekday itself by using date("D", [timestamp]), but I'm not sure how to calculate that it is in fact the third one this month.
Has anyone tried doing anything like this before?
You'll want to verify you're working within a valid date range, but this is a relatively simple task:
$today = date('d', time());
echo 1 + floor(($today - 1) / 7); // nth day of month
You should look into the Carbon class. It expands date and time functions to basically everything you'd ever need, including human-readable timestamps (ie. "5 minutes ago")
These two would be useful to you - the day and week of the month.
var_dump($dt->dayOfWeek); // int(3)
var_dump($dt->weekOfMonth); // int(1)
http://carbon.nesbot.com/docs/#api-getters
What's wrong with my code? I want my script to check if it is Monday and is greater or equal to 22:00 and less than or equal to 23:00.
$t = date("D:G:i");
if ($t >= "Mon:22:00" && $t <= "Mon:23:00") {
$status = "up";
} else {
$status = "down";
}
you cannot compare strings (it is not dates, it is just strings of arbitrary symbols), as we're not code-writing monkeys I'll just describe how you should do it instead of providing copy-pastable code:
get weekday number, hour, minute from current time into 3 separate variables
compare weekday variable with monday value
if weekdays are ok - compare hours with 22
minutes can be omitted here, if you check for [22, 23), or you need to make additional comparison for 23:00 case
another approach - generate unix timestamps for the closest monday 22 and 23 hours, and then numeric comparisons
You're comparing two strings instead of two numerical values. Not ideal at all. You want to look into converting the dates into a Unix timestamp and comparing those values.
mktime: http://php.net/manual/en/function.mktime.php
mktime will allow you to get a Unix timestamp for any date.
time: http://php.net/manual/en/function.time.php
time will give you the current date and time as a Unix timestamp.
You can then compare to find out which is larger/smaller than the other.
I need to get an array of dates except sunday and optional saturday by a specific day count... I found a cool thing - dateperiod, witch gives array to me, but how to exclude sunday and saturday?
Try this...
$daterange = new DatePeriod(...);
$weekdays = [];
foreach($daterange as $date){
if ($date->format("N") < 6) array_push($weekdays, $date);
}
$weekdays should now contain every date object that isn't the 6th or greater day of the week (that is, Saturday or Sunday)
As Simon M says, that seems to be the solution to this issue, it has been answered here too Get date range between two dates excluding weekends
It's a bit disconcerting there's not an option on DatePeriod to exclude days.