Get weekday by number - php

We all know date('w').
What I am trying to do is to find the next Date with the index retrieved from another date('w').
I tried:
$saturday = 6;
if((int)date('w') < $saturday){
$targetdate = strtotime('last Sunday +'.$saturday.' days');
}else{
$targetdate = strtotime('next Sunday +'.$saturday.' days');
}
But it ist not as reliable as I hoped when today is sunday.
Any best practice on this?

I could not find a quick way to do that. But I found a passable way around it (in case it helps someone):
$days = array(
0 => 'Sunday',
1 => 'Monday',
2 => 'Tuesday',
3 => 'Wednesday',
4 => 'Thursday',
5 => 'Friday',
6 => 'Saturday'
);
$targetdate = strtotime('next '.$saturday]);

Please just do:
date("l", strtotime("monday +$weekday_index days" ) )
Smoother than having to define an array each time!

Related

Not able to output "total registrations today" count

I am trying to output the count of total registrations today, registrations in the last 7 days, last 30 days.
All the other counts are output as expected. Except for registrations today.
$registration_summery = [
'Registrations today' => '+0 days',
'Registrations in the last 7 Days' => '-7 days',
'Registrations in the last 15 Days' => '-15 days',
'Registrations in the last 30 Days' => '-30 days',
'Registrations in the last 6 month' => '-6 months',
'Registrations in the last 1 year' => '-1 Years'
];
$toReturn['registration_summery'][] = ['name' => 'Total Learners', 'value' => \DB::table('users')->where('users.role', 'student')->count()];
foreach ($registration_summery as $key => $value) {
$tmp = \DB::table('users')->where('role', 'student')
->where('createdAt', '>=', strtotime("tomorrow", strtotime($value)) - 1)
->where('createdAt', '<=', strtotime("midnight"))
->count();
$toReturn['registration_summery'][] = ['name' => $key, 'value' => $tmp];
}
No Errors, but the count shows 0
You can achieve that by substracting 23 hours more like this.
$registration_summery = [
'Registrations today' => '+0 days -23Hours',
// rest data.....
Fixed this.
Changed line 2 to -1 days.
$registration_summery = ['Registrations today' => '-1 days', 'Registrations in the last 7 Days' => '-7 days',
and changed "midnight" to "tomorrow"
->where('createdAt', '<=', strtotime("tomorrow"))
Thank you #rahul for your help

How can I loop dates for a specified time?

I need to loop dates, according to different $eventname. I was already able to write a script that adds one week to the original date, but I don't know how I can loop it for a defined time.
code used:
$eventname = $event->title;
// TODO: loop for specified times if $eventname contains definded strings
$start_date = helper('com://site/ohanah.date.format', array(
'date' => $event->start,
'format' => 'Y/m/d H:i',
'timezone' => 'UTC'
));
$date = strtotime($start_date) + 604800;
echo "<pre>";
echo date('d. F Y, H:i', $date);
echo ' - ';
echo helper('com://site/ohanah.date.format', array(
'date' => $event->end,
'format' => 'H:i',
'timezone' => 'UTC'
));
echo "</pre>";
Output: (start date would be one week before) 18. April 2018, 14:00 - 16:00
So my question is, how can I loop this that the output is e.g. 6 times with one week space between each of them?
When working with dates and times, do not add seconds to timestamps or something like that, because it will get you in trouble in leapyears and daylight saving times, because one day is not always 86400 seconds.
Better use PHP's DateTime and DateInterval classes.
<?php
$Date = new DateTime("2018-03-03 14:00:00");
for($i=0;$i<6;$i++) { //loop 6 times
$Date->add(new DateInterval('P1W')); //add one week
echo $Date->format("Y-m-d H:i:s").PHP_EOL;
}
Output:
2018-03-10 14:00:00
2018-03-17 14:00:00
2018-03-24 14:00:00
2018-03-31 14:00:00
2018-04-07 14:00:00
See also:
http://php.net/manual/en/class.datetime.php
http://php.net/manual/en/class.dateinterval.php
Something like that?
<?php
$oneWeek = 604800;
$date = '2018-04-05';
$dates = array($date);
for ($i = 0; $i < 6; $i++) {
$dates[] = $date = date('Y-m-d', strtotime($date) + $oneWeek);
}
var_dump($dates);
I am not entirely sure I understand the question, but it looks like you want to have a condition that will either set a specific number of times for the output loop or determine whether the loop is ran that number of times.
If so, you can set a counter variable with your condition, then run the loop that number of times, defaulting the counter variable to 1 in the case that you do not want to output more than one time:
$eventname = $event->title;
// TODO: loop for specified times if $eventname contains definded strings
$counter = (/*your condition for $eventname*/) ? 6 : 1;
for ($x = 0; $x < $counter; $x++) {
$start_date = helper('com://site/ohanah.date.format', array(
'date' => $event->start,
'format' => 'Y/m/d H:i',
'timezone' => 'UTC'
));
$date = strtotime($start_date) + 604800;
echo "<pre>";
echo date('d. F Y, H:i', $date);
echo ' - ';
echo helper('com://site/ohanah.date.format', array(
'date' => $event->end,
'format' => 'H:i',
'timezone' => 'UTC'
));
echo "</pre>";
}

Converting birthday in format DDMMMYY to date value in PHP

I've got bunch of birthdays which are stored in format DDMMMYY. I need to convert those to date values, so i can store those in database.
Is there any easy way of telling strtotime function that date must be in the past?
<?php
$datestring = '22SEP41';
echo date('Y-m-d',strtotime($datestring)); //outputs 2041-09-22, should be 1941-09-22
?>
<?php
$datestring = '22SEP41';
$matches = [];
preg_match('/([0-9]{2})([A-Z]{3})([0-9]{2})/', $datestring, $matches);
$prefix = ($matches[3] <= date('y') ? '20' : '19');
$matches[3] = "{$prefix}{$matches[3]}";
$ts = strtotime("{$matches[1]} {$matches[2]} {$matches[3]}");
// date ('Y-m-d', $ts) == 1941-09-22
This assumes that 22SEP06 should be interpreted as 2006 rather than 1906 - basically it gives the output a range of 1917 -> 2016.
This method create a date of past century only if standard evaluated date is after today:
$date = date_create( $datestring );
if( $date->diff( date_create() )->invert )
{
$date->modify( '-100 years' );
}
echo $date->format( 'Y-m-d' );
For
$datestring = '22SEP41';
the output is:
1941-09-22
For
$datestring = '22SEP01';
the output is:
2001-09-22
eval.in demo
Basically, we create a DateTime based on given string, then we calculate difference with current day; if the difference is negative (->invert), we subtract 1 century from the date.
You can personalize the condition using ->format('%R%Y') instead of ->invert. In this example:
if( $date->diff( date_create() )->format('%R%Y') < 10 )
Dates from 00 through 05 as evaluated as 2000-2005.
You could try something like:
$ds = '22SEP41';
$day = $ds[0].$ds[1];
// Getting the month.
$mon = array(
'JAN' => 1,
'FEB' => 2,
'MAR' => 3,
'APR' => 4,
'MAY' => 5,
'JUN' => 6,
'JUL' => 7,
'AUG' => 8,
'SEP' => 9,
'OCT' => 10,
'NOV' => 11,
'DEC' => 12
);
$mont = $ds[2].$ds[3].$ds[4];
$month = $mon[$mont]; // Gets the month real.
$year = '19'.$ds[5].$ds[6];
$final = $day.'-'.$month.'-'.$year;
I tested it on my local machine and it worked. Hope it works and is what you're looking for :)

Can not figure out why results do not match the date range that was specified with DateTime()

I already tried to find the answer by myself with the help of related posts like:
The first day of the current month in php using date_modify as DateTime object
PHP strtotime +1 month behaviour
PHP DateTime::modify adding and subtracting months
but unfortunately I wasn't able to find my mistake :-/ So I'm asking you for your support.
I'm currently trying to customize a wordpress theme for an event website and I'd like to enhance the existing search options with a filter by month.
I have a select box that contains all month from January - December:
<select id="listingFormTime" name="listingFormTime">
<option value=""<?php selected( $time, "" ); ?>><?php _e( "Any Time", "themesdojo" ); ?></option>
<option value="1"<?php selected( $time, 1 ); ?>><?php _e( "January", "themesdojo" ); ?></option>
<option value="2"<?php selected( $time, 2 ); ?>><?php _e( "February", "themesdojo" ); ?></option>
<option value="3"<?php selected( $time, 3 ); ?>><?php _e( "March", "themesdojo" ); ?></option>
...
<option value="12"<?php selected( $time, 12 ); ?>><?php _e( "December", "themesdojo" ); ?></option>
</select>
when selecting a month the corresponding records should be picked from the database and should be displayed. When selecting "March" all events that have their start date in March should be listed, etc.
The necessary event dates are stored in an additional table as "meta_key" and "meta_value"
event_start_date --> e.g.: 02/20/2016
event_start_time --> e.g.: 3:00 PM
event_start_date_number --> e.g.: 1455980400
event_end_date --> e.g.: 02/20/2016
event_end_time --> e.g.: 7:00 PM
event_end_date_number --> e.g.: 1455994800
I found out that I can use DateTime(); and have the option to modify and also use relative formats. So firstly I added the following 12 queries for each month:
if($time == 1) {
$dt_min = new DateTime('2015-12-31'); // January
$dt_max = clone($dt_min);
$dt_max->modify('+1 month');
$end_date = $dt_max->format('m/d/Y');
$date = $end_date." 23:59:59";
$event_start_date_number = strtotime($date); erzeugen
$time_args = array(
'key' => 'event_start_date_number',
'value' => $event_start_date_number,
'compare' => '<=',
'orderby' => 'value',
'order' => 'ASC',
);
} elseif($time == 2) {
$dt_min = new DateTime('2016-01-31'); // February
$dt_max = clone($dt_min);
$dt_max->modify('+1 month');
$end_date = $dt_max->format('m/d/Y');
$date = $end_date." 23:59:59";
$event_start_date_number = strtotime($date);
$time_args = array(
'key' => 'event_start_date_number',
'value' => $event_start_date_number,
'compare' => '<=',
'orderby' => 'value',
'order' => 'ASC',
);
...
} elseif($time == 12) { ...
Then I read that "modify('+1 month');" could lead to problems and found out that my results works perfectly for February but from March on the results aren't correct any longer.
So I tried to find another solution and tried to use another relative format: $dt_max->modify('last day of January 2016'); instead of $dt_max->modify('+1 month');
if($time == 1) {
$dt_min = new DateTime('2016-01-01');
$dt_max = clone($dt_min);
$dt_max->modify('last day of January 2016');
$end_date = $dt_max->format('m/d/Y');
$date = $end_date." 23:59:59";
$event_start_date_number = strtotime($date);
$time_args = array(
'key' => 'event_start_date_number',
'value' => $event_start_date_number,
'compare' => '<=',
'orderby' => 'value',
'order' => 'ASC',
);
} elseif($time == 2) {
$dt_min = new DateTime('2016-02-01');
$dt_max = clone($dt_min);
$dt_max->modify('last day of February 2016');
$end_date = $dt_max->format('m/d/Y');
$date = $end_date." 23:59:59";
$event_start_date_number = strtotime($date);
$time_args = array(
'key' => 'event_start_date_number',
'value' => $event_start_date_number,
'compare' => '<=',
'orderby' => 'value',
'order' => 'ASC',
);
Unfortunately same result here - February is fine but in March also the February events are shown. In April the events from February AND March are shown. It seems as if the next month's events are simply added and I do not know why ;-(
I thought when setting the new DateTime() each time to the beginning of the month the duration is limited?!
I am very sorry in case that this is a dumb question - I'm not a developer and have very poor programming skills but willing to learn. Your help and experiences are really appreciated.
After using:
var_dump($dt_min );
var_dump($dt_max );
var_dump($date );
var_dump($end_date );
var_dump($event_start_date_number );
I firstly get results as expected, so I can be sure that the variables are filled with information and datetime is working properly:
$dt_min --> object(DateTime)#5820 (3) { ["date"]=> string(26) "2016-01-01 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
$dt_max --> object(DateTime)#5819 (3) { ["date"]=> string(26) "2016-01-31 00:00:00.000000" ["timezone_type"]=> int(3) ["timezone"]=> string(3) "UTC" }
$date --> string(19) "01/31/2016 23:59:59"
$end_date --> string(10) "01/31/2016"
$event_start_date_number = int(1454284799) // 01. Februar 2016, 00:59:59 UTC+1
But there are two issues that are confusing:
$event_start_date_number = int(1454284799) // 01. Februar 2016, 00:59:59 UTC+1
the generated $event_start_date_number in UNIX Time should be 01/31/2016 23:59:59 in my understanding. But when decoding it there seem to be +1 hour to my timezone (GMT +1 Berlin) in January and from March it differs to +2 hours to my timezone (GMT +2 Berlin) - I guess this is due to Daylight Time, but I will have to consider this to make the correct events show up.
Is there a way to influence the timezone or can I subtract -1 or -2 hours from the Unix timestamp?
The second issue I figured out is:
(...)
$time_args = array(
'key' => 'event_start_date_number',
'value' => $event_start_date_number,
'compare' => '<=',
'orderby' => 'value',
'order' => 'ASC',
);
Could it be that I am only selecting events which start dates are smaller than the end date I defined? This would explain, why all events from the previous month are always listed -,-
I thought that I will limit the duration for the event selection with
$dt_min = new DateTime('2016-02-01');
$dt_max = clone($dt_min);
$dt_max->modify('last day of February 2016');
But in the array there seem to be no limitation from which starting point the events should be listed.
Is there a way to enhance the array in a way that only events are listed whose event_start_date_number is between $dt_min and dt_max?
Ok I figured it out by myself
Is there a way to influence the timezone or can I subtract -1 or -2 hours from the Unix timestamp?
I did it with a workaround and quick & dirty fix by editing the startdate and time in winter and summer to fix this +1 / +2 hour issue - even if I'm aware that there will be a few days the problem will still occur:
//WINTER (January, February, March, November, December)
$dt_min = new DateTime('2015-12-31'); // --> 01.01.2016
(...)
$start = $start_date." 23:00:01"; // --> 00:00:01 (+1 hour)
(...)
$end = $end_date." 22:59:59"; // --> 23:59:59 (+1 hour)
//SUMMER (April - October)
$dt_min = new DateTime('2015-03-31'); // --> 01.04.2016
(...)
$start = $start_date." 22:00:01"; // --> 00:00:01 (+2 hours)
(...)
$end = $end_date." 21:59:59"; // --> 23:59:59 (+2 hours)
For the second question I found a better solution with no workaround
Is there a way to enhance the array in a way that only events are listed whose event_start_date_number is between $dt_min and dt_max?
} elseif($time == 4) {
$dt_min = new DateTime('2016-03-31');
$dt_max = clone($dt_min);
$dt_max->modify('last day of April 2016');
// additionally defined a start date for the range based on $dt_min
$start_date = $dt_min->format('m/d/Y');
$start = $start_date." 22:00:01";
$start_date_number = strtotime($start);
$end_date = $dt_max->format('m/d/Y');
$end = $end_date." 21:59:59";
$event_start_date_number = strtotime($end);
// found out that I can have an array in an array ^^ to define the date range
$time_args = array(
'key' => 'event_start_date_number',
'value' => array ($start_date_number, $event_start_date_number),
'compare' => 'BETWEEN',
'orderby' => 'value',
'order' => 'ASC',
);
For now my problem is "solved" because the correct events are listed when selecting a month.

Determining shop opening times in PHP

I'd like to include some text on my website that states whether or not a shop is open based on its opening times. If the shop is open, it says when it's open until. If it's not open, it says when it's next open.
I already have the opening times stored in the following variable:
$opening_times = [
'Monday' => ['09:00' => '17:00'],
'Tuesday' => ['09:00' => '17:00'],
'Wednesday' => ['09:00' => '12:00'],
'Thursday' => ['09:00' => '17:00'],
'Friday' => ['09:00' => '17:00'],
'Saturday' => ['09:30' => '17:00']
];
The shop is closed on Sunday.
Please could someone guide me as to how I can do this? I've already looked at this example but I'm unsure how to handle showing the time the shop is open next and what to do when it's a Sunday.
I'm hoping to finish with something that displays the next time the shop's open, whether that's on the same day or not. For example, at 5.30pm on Saturday, I'd like the message to say that the shop's next open at 9am on Monday.
I had previously attempted this by storing the next open day and time with each day in the $opening_times variable but I was wondering if there was a more elegant solution.
Using the answer here: Determine If Business Is Open/Closed Based On Business Hours as a guide.
This takes into account opening later and not opening today at all.
UPDATE: Tells you when it is next open. (Untested because work servers use PHP 5.3 :()
<?php
$storeSchedule = [
'Sun' => [['12:00' => '01:00', '09:00' => '12:00']],
'Mon' => [['09:00' => '12:00']],
'Tue' => [['09:00' => '12:00']],
'Wed' => [['09:00' => '12:00']],
'Thu' => [['09:00' => '12:00'], ['22:50' => '23:00']],
'Fri' => [['09:00' => '12:00']],
'Sat' => [['12:00' => '01:00', '09:00' => '12:00']]
];
// current or user supplied UNIX timestamp
$timestamp = time();
// default status
$open = false;
// Open later at
$openAt = false;
// get current time object
$currentTime = (new DateTime())->setTimestamp($timestamp);
// Current day
$currentDay = date('D', $timestamp);
if(isset($storeSchedule[$currentDay])){
// loop through time ranges for current day
foreach ($storeSchedule[$currentDay] as $key => $dateGroup) {
$startTime = current(array_keys($dateGroup));
$endTime = current(array_values($dateGroup));
// create time objects from start/end times
$startTime = DateTime::createFromFormat('H:i', $startTime);
$endTime = DateTime::createFromFormat('H:i', $endTime);
// check if current time is within a range
if (($startTime < $currentTime) && ($currentTime < $endTime)) {
$open = true;
break;
}elseif($currentTime < $startTime){
// Opening Later
$openAt = $startTime;
}
}
}else{
// Not open because day is not in array
}
if($open){
echo "We are open";
}else{
if($openAt){
echo "We open later at " . $openAt->format('H:i');
}else{
// Get next open
$arrayDays = array_keys($storeSchedule); // Get an array of the days
$arrayTimes = array_values($storeSchedule); // Get an array of times
$dayIndex = array_search($currentDay, $arrayDays); // Find out what day we are in in the array. To see if there are more this week
$nextDay = ($dayIndex + 1) >= count($arrayDays) ? $arrayTimes[0] : $arrayTimes[$dayIndex + 1]; // If there are no more this week, take the first day, else take the next day.
$nextOpenTime = current(array_keys($nextDay)); // Take the first set of times from this day as the start time
$nextOpenDay = $arrayDays[$dayIndex + 1]; // Get the day key name
echo "We are not open";
echo "We open next on " . $nextOpenDay . " at " . $nextOpenTime->format('H:i');
}
}
?>

Categories