Check if weekday is between weekdays in string - php

So i have a list of weekdays in which i need to check if they are the current day. The list varies between either being 'Monday/Tuesday' and 'Wednesday - Friday'
My current solution is string comparison, so it only detects if the current weekday is written in the list item.
Heres the current solution (in PHP btw):
setlocale(LC_ALL, "danish");
$day = get_sub_field('dag'); // the field containing the user input day
$currentDay = strftime('%a', mktime());
$currentDayLower = strtolower($currentDay);
$dayLowercase = strtolower($day);
$class = '';
if(strpos($dayLowercase, $currentDayLower) !== false ){
$class = ' current-day';
} else{
$class = '';
}
I was thinking about having an array of all weekdays and comparing the user field to current day position in the array, but im not sure if that would be efficient or even possible.
Is there any obvious or alternative method that could be easier than what I'm currently doing?
Any inputs are greatly appreciated.
EDIT:
I found a working solution, which i posted as an answer (I can't choose it as the answer for 2 days though). Thanks for the inputs!

Yes, your idea is feasible and it should not affect performance badly unless you do this many times in a short period of time, where many starts at a scale of hundreds of thousands. Notice that I have created an array of $weekdays and notice that when you assign a value for $class, that is an end sign for the cycle as well.
setlocale(LC_ALL, "danish");
$day = get_sub_field('dag'); // the field containing the user input day
$dayLowercase = strtolower($day);
$weekdays = array("monday", "tuesday", "wednesday", "thursday", "friday");
$class = '';
for ($index = 0, (!$class) && ($index < 5); $index++) {
if(strpos($dayLowercase, $weekdays[$index]) !== false ){
$class = ' current-day';
} else{
$class = '';
}
}

If you want to check that the range of days includes the current day, you can do the following.
$period = 'Wednesday-Friday';
$limitDays = explode('-', $period);
$startDayName = trim(strtolower($limitDays[0]));
$endDayName = trim(strtolower($limitDays[1]));
$today = new DateTime();
$todayName = strtolower($today->format('l'));
// Check if the startDay or endDay is today.
echo "$startDayName $endDayName $todayName\n";
if ($startDayName === $todayName || $endDayName === $todayName) {
echo "Same day\n";
$class = 'current-day';
} else {
// Get a date time representing the start day.
$startDay = new \DateTime();
$startDay->modify("next $startDayName");
// Based on the start day, get the next current day.
$thisDay = new \DateTime();
$thisDay->modify("next $startDayName");
$thisDay->modify("next $todayName");
// Based on the start day, get the next end day.
$endDay = new \DateTime();
$endDay->modify("next $startDayName");
$endDay->modify("next $endDayName");
// Check if thisDay is between the startDay and endDay.
if ($startDay < $thisDay && $thisDay < $endDay) {
$class = 'current-day';
} else {
$class = '';
}
}
echo $class . "\n";
I'm not sure that this is easier or more efficient, but it's not a bad way to do this.

So as i found out, its rather complicated making a datetime from a Danish weekday string. A lot easier to go from English and format to Danish.
So i had to make it a bit different, by stitching parts of you guys' answers together.
<?php while ( have_rows('aabningstider_repeater', 'option') ) : the_row();
// vars
$day = get_sub_field('dag');
$timer = get_sub_field('aabne_timer');
$dayLower = strtolower($day);
$weekArray = array('mandag', 'tirsdag', 'onsdag', 'torsdag', 'fredag', 'lørdag', 'søndag' );
$dayArray = preg_split('/[\s,-]+/', $dayLower);
$today = date('w') - 1;
$class = '';
if(is_array($dayArray)){
$days = [];
foreach ($dayArray as $daySingle ) {
array_push($days, array_search($daySingle, $weekArray));
}
if($today > $days[0] && $today < $days[1]){
$class = ' current-day in-between-days';
} elseif($today == $days[0] || $today == $days[1]){
$class = ' current-day';
} else{
$class = '';
}
}
endwhile; ?>
I'm pretty sure this will work untill i one day detect a major flaw. Until then it'll do.
Any feedback or optimization is greatly appreciated. And thanks for all the inputs!

setlocale(LC_ALL, "danish");
$day = get_sub_field('dag'); // the field containing the user input day
$currentDayLower = strtolower(date("D"));
$dayLowercase = strtolower($day);
$class = '';
if($dayLowercase === $currentDayLower)
$class = ' current-day';

Related

php - if date older than 6 months ago

I want the below code to check the created date of a customer, if they have been a customer for 6 months the price goes up as it was a promotion. I tried the below with no joy, I think as its just using the month and not taking the year into account. For example if a customer came onboard in September the 6 month would be the next year and it never change.
Thanks
$created_date = date('m',strtotime($customer_order['created_at']));
$current = date("m");
$curmonth = date("m");
$ordermonth = date("m",strtotime($udata['created_date']));
$m_dff = $curmonth - $ordermonth;
//print_r($m_dff."<br>");
if($m_dff > 6){
$unitcost = 19.99;
}
else{
$unitcost = 14.99;
}
strtotime() can be used more effectively than in your example, the following should do the trick
if(time() > strtotime($customer_order['created_at'] . ' +6 months')) {
$unitcost = 19.99;
} else {
$unitcost = 14.99;
}
$currentorder = date ('Y-m-d');
$createdaccount = date('Y-m-d', strtotime("+6 months",
strtotime($customer_order['created_at'])));
if($currentorder>=$createdaccount)
{
$unitcost = 19.99;
}
else
{
$unitcost = 14.99;
}
See if this works using DateTime objects to compare.
//set a general time zone at top of script
date_default_timezone_set('Europe/Amsterdam');
// if created_at is a valid dateTime string
$created = new \DateTime($customer_order['created_at']);
$current = new \DateTime();
$sixMonth = $created->add(new \DateInterval(‘P6M’));
if ($created < $current) {
// if created + 6 months is older than current
$price = 19.99;
} else {
$price = 14.99;
}
For more info see: https://secure.php.net/manual/en/book.datetime.php

php carbon check if now is between two times (10pm-8am)

$start = '22:00:00';
$end = '08:00:00';
$now = Carbon::now('UTC');
How can I check if the time of $now is within the timerange?
There are several ways to achieve that by using Carbon. One of the easiest ways is using createFromTimeString and between methods:
$now = Carbon::now();
$start = Carbon::createFromTimeString('22:00');
$end = Carbon::createFromTimeString('08:00')->addDay();
if ($now->between($start, $end)) {
// ¯\_(ツ)_/¯
}
Try this:
$time = Carbon::now();
$morning = Carbon::create($time->year, $time->month, $time->day, 8, 0, 0); //set time to 08:00
$evening = Carbon::create($time->year, $time->month, $time->day, 18, 0, 0); //set time to 18:00
if($time->between($morning, $evening, true)) {
//current time is between morning and evening
} else {
//current time is earlier than morning or later than evening
}
The true in $time->between($morning, $evening, true) checks whether the $time is between and including $morning and $evening. If you write false instead it checks just if it is between the two times but not including.
Actually, you could leave true away because it is set by default and not needed.
Check here for more information on how to compare dates and times with Carbon.
$start = '22:00:00';
$end = '08:00:00';
$now = Carbon::now('UTC');
$time = $now->format('H:i:s');
if ($time >= $start && $time <= $end) {
...
}
Should do it, but doesn't take date into consideration
You can reverse check algorithm.
<?php
$pushChannel = "general";
$now = Carbon::now();
$start = Carbon::createFromTime(8, 0);
$end = Carbon::createFromTime(22, 0);
if (!$now->between($start, $end)) {
$pushChannel = "silent";
$restrictStartTime = Carbon::createFromTime(22, 0, 0); //carbon inbuild function which will create todays date with the given time
$restrictEndTime = Carbon::createFromTime(8, 0, 0)->addDays(1); //this will create tomorrows date with the given time
$now = Carbon::now();
if($now->gt($restrictStartTime) && $now->lt($restrictEndTime)) {
.....
}
Please Try below code,
$start = '22:00:00';
$end = '08:00:00';
$now = Carbon::now('UTC');
$nowTime = $now->hour.':'.$now->minute.':'.$now->second;
if(strtotime($nowTime) > strtotime($start) && strtotime($nowTime) < strtotime($end) ) {
echo 'YES';
} else {
echo 'NO';
}
What Chris is trying to point out is if the endtime crosses over midnight then you must account for that.
This is not the cleanest way to do it but here is a method that seems to work.
private function isNowBetweenTimes($timezone, $startDateTime, $endDateTime) {
$curTimeLocal = Carbon::now($timezone);
$startTime = $curTimeLocal->copy();
$startTime->hour = $startDateTime->hour;
$startTime->minute = $startDateTime->minute;
$endTime = $curTimeLocal->copy();
$endTime->hour = $endDateTime->hour;
$endTime->minute = $endDateTime->minute;
if ($endTime->lessThan($startTime))
$endTime->addDay();
return ($curTimeLocal->isBetween($startTime, $endTime));
}
This example only cares about the hour and minutes and not the seconds but you can easily copy that as well. The key to this is comparing start and end time before comparing them to the current time and add a day to end time if end time is less than start time.
For complete solution which supports all start and end time range you can use bitwise XOR.
/*
* must using hours in 24 hours format e.g. set 0 for 12 pm, 6 for 6 am and 13 for 1 pm
*/
private $startTime = '0';
private $endTime = '6';
$currentHour = \Carbon\Carbon::now()->hour;
$start = $this->startTime > $this->endTime ? !($this->startTime <= $currentHour) : $this->startTime <= $currentHour;
$end = $currentHour < $this->endTime;
if (!($start ^ $end)) {
//Do stuff here if you want exactly between start and end time
}
an updated version of #AliN11's answer taking into account ranges accross two days or in the same day
$now = now();
$start = Carbon::createFromTimeString('22:00');
$end = Carbon::createFromTimeString('08:00');
if ($start > $end) {
$end = $end->addDay();
}
if ($now->between($start, $end)||$now->addDay()->between($start, $end)) {
//add statements
}
<?php
$now = date("H");
if ($now < "20") {
echo "Have a good day!";
}
Try this :
$start = 22; //Eg. start hour
$end = 08; //Eg. end hour
$now = Carbon::now('UTC');
if( $start < $now->hour && $now->hour < $end){
// Do something
}
#AliN11's (currently top) answer is good, but doesn't work as one would immediately expect, after midnight it just breaks, as raised in the comments by #Sasha
The solution is to reverse the logic, and check if the time is not between the inverse hours.
Here is an alternative that works as one would expect:
$now = Carbon::now();
$start = Carbon::createFromTimeString('08:00');
$end = Carbon::createFromTimeString('22:00');
if (! $now->between($start, $end)) {
// We're all good
}
Yes, the midnight plays a vital role in time duration. We can find now() being the given time range as follows:
$now = Carbon::now();
$start = Carbon::createFromTime('22', '00');
$end = Carbon::createFromTime('08', '00');
if ($start->gt($end)) {
if ($now->gte($start)) {
$end->addDay();
} elseif ($now->lte($end)) {
$start->subDay();
} else {
return false;
}
}
return $now->between($start, $end);

PHP - Finding consecutive day counts in an array

Let's say I have an array called $selectedDates containing the following
$selectedDates = [
"2000-01-31",
"2000-02-01",
"2000-02-02",
"2000-02-20"
];
Is there some way in PHP to calculate out what # each day is consecutively.
So that the first one returns 1, the 2nd one would be returning 2, the 3rd would be 3 but the 4th would be 1 again.
I'm trying to loop through them all at the moment but am not really getitng anywhere.
<?php foreach ($selectedDates as $date): ?>
Seriously lost about what to put here.
<?php echo $consecDayCount; ?>
<?php endforeach; ?>
I'm thinking inside of the loop I may need to loop through it again? And start at the first one and check each day going up one more, adding to some incrementer for each day that says the previous date in the array was the previous day in time. I'm just kind of banging my head against a wall figuring out that part.
One way to Rome...
# We assume $selectedDates is sorted at this point.
$selectedDates = [
"2000-01-31",
"2000-02-01",
"2000-02-02",
"2000-02-20"
];
# The array we will print.
$coll = array();
# We use array_reverse to start from the last entry.
foreach(array_reverse($selectedDates) as $date) {
$tmp = $date;
$con = 1;
do $tmp = date('Y-m-d', strtotime("$tmp -1day"));
# ++$con is used to count only up if in_array gives true.
while(in_array($tmp, $selectedDates) && (++$con));
$coll[$date] = $con;
}
print_r($coll);
Result: Array ( [2000-02-20] => 1 [2000-02-02] => 3 [2000-02-01] => 2 [2000-01-31] => 1 )
Here you go:
$selectedDates = [
'2000-01-31',
'2000-02-01',
'2000-02-02',
'2000-02-20',
'2000-02-21',
];
$format = 'Y-m-d';
$consecutive = [];
$length = count($selectedDates);
$streak = false;
$last = null;
for($index = 0; $index < $length - 1; $index++) {
$firstDate = DateTime::createFromFormat($format, $selectedDates[$index]);
$secondDate = DateTime::createFromFormat($format, $selectedDates[$index + 1]);
$diff = $firstDate->diff($secondDate);
if ($diff->days === 1) {
// consecutive dates
if ($streak) {
$consecutive[$last]++; // we have another consecutive day to the current streak
} else {
$consecutive[$selectedDates[$index]] = 2; // we already have 2 consecutive days
$last = $selectedDates[$index];
$streak = true;
}
} else {
$streak = false;
}
}
var_dump($consecutive);
This will give you an array in the date => number of consecutive days starting on that date format.
Another way
$dates = array(
new DateTime('2000-01-31'),
new DateTime('2000-02-01'),
new DateTime('2000-02-02'),
new DateTime('2000-02-20'),
);
// process the array
$lastDate = null;
$ranges = array();
$currentRange = array();
foreach ($dates as $date) {
if (null === $lastDate) {
$currentRange[] = $date;
} else {
// get the DateInterval object
$interval = $date->diff($lastDate);
// DateInterval has properties for
// days, weeks. months etc. You should
// implement some more robust conditions here to
// make sure all you're not getting false matches
// for diffs like a month and a day, a year and
// a day and so on...
if ($interval->days === 1) {
// add this date to the current range
$currentRange[] = $date;
} else {
// store the old range and start anew
$ranges[] = $currentRange;
$currentRange = array($date);
}
}
// end of iteration...
// this date is now the last date
$lastDate = $date;
}
// messy...
$ranges[] = $currentRange;
// print dates
foreach ($ranges as $range) {
// there'll always be one array element, so
// shift that off and create a string from the date object
$startDate = array_shift($range);
$str = sprintf('%s', $startDate->format('D j M'));
// if there are still elements in $range
// then this is a range. pop off the last
// element, do the same as above and concatenate
if (count($range)) {
$endDate = array_pop($range);
$str .= sprintf(' to %s', $endDate->format('D j M'));
}
echo "<p>$str</p>";
} ?>
output::: Mon 31 Jan to Wed 2 Feb
Sun 20 Feb

check if variable is higher than item in array php

I want to check if a variable is greater than or equal to an item in an array.
I've tried multiple for loops, but then they just stack and stack and stack. I just need to get the dates, for example: 01-01-2005 / 01-01-2006
and compare those two both with today's date and check if today's date is greater then or equal to the date of the book. And if the book is older then today's date do some code
foreach ($user_out as $userOut) {
$userOut_id[] = $userOut['user_id'];
}
$userOut_id_implode = implode(',',$userOut_id);
//loop through each element from the tocomet able
$dateOfBook = [];
$today = date("d-m-Y");
foreach ($out as $outs) {
$datum = $outs['released'];
//gets the date of the selected book.
$bookDate = date("d-m-Y", strtotime($datum));
$dateOfBook[] = $outs['released'];
//gets the name of the author
$author_name = $outs['author'];
//gets the title of the book
$book_title = $outs['book_title'];
$today = strtotime($today);
$bookDate = strtotime($bookDate);
//checks if today is equal or smaller then the bookdate
}
$today = date("Y-m-d");
$y = count($dateOfBook);
for($x = 0; $x < $y; $x++){
echo $x;
};
if($today >= $dateOfBook($x)){
do stuff
}
$dateOfBook = [];
$today = date("d-m-Y");
$flag = 0;
foreach ($out as $outs) {
//gets the date of the book out of the database
if($today >= $outs['released']){
$flag++;
}
$dateOfBook[] = $outs['released']; # is this necessary?
}
if($flag){
# do something
}

Average day of month from list of dates in PHP

I'm trying to find the average date and guess the next one.
The input is a list of dates that looks like this:
$completeDate = array(
'2015-04-13T00:00:00-0800',
'2015-03-20T00:00:00-0800',
'2015-02-17T00:00:00-0800',
'2015-01-10T00:00:00-0800'
);
I'm trying to scan a list of x amount of dates, and output an average of the dates overall.
So in the above example I think the output would be 2015-5-15 is expected average date.
How would I tackle this?
If you're looking for the average of those dates you can simply get the day of the year for each of those dates, average them out, and use that date:
$completeDate = array(
'2015-04-13T00:00:00-0800',
'2015-03-20T00:00:00-0800',
'2015-02-17T00:00:00-0800',
'2015-01-10T00:00:00-0800'
);
$first = null;
$last = null;
foreach($completeDate as $date) {
$dayOfYear = (new DateTime($date))->format('z');
if (is_null($first)) {
$first = $last = $dayOfYear;
}
else {
if ($dt < $first) {
$first = $dayOfYear;
}
if ($dt > $last) {
$last = $dayOfYear;
}
}
}
$avg = round(($first + $last) / 2);
$averageDate = DateTime::createFromFormat('z', $avg);
echo $averageDate->format('Y-m-d'); // 2015-02-26
Demo
If your looking for the average of the day of the month for the dates in that array and then use that day of the next month, you just need to average out the days of the month and then use that with the next month:
$completeDate = array(
'2015-04-13T00:00:00-0800',
'2015-03-20T00:00:00-0800',
'2015-02-17T00:00:00-0800',
'2015-01-10T00:00:00-0800'
);
$month = 0;
$days = 0;
foreach($completeDate as $date) {
$dt = new DateTime($date);
$month_num = $dt->format('n');
if ($month_num > $month) {
$month = $month_num;
}
$days += $dt->format('j');
}
$avg = round($days / count($completeDate));
$date = new DateTime(sprintf('%d-%01d-%01d', $dt->format('Y'), ++$month, $avg));
echo $date->format('Y-m-d'); // 2015-05-15
Demo

Categories