php first week number every month - php

Don,t think I can find this answer in this forum.
How to get the first week number in every month where month start by Monday. This month first week is 36 how to get that? Having this code. But don't work.
//get first week number in month
$month = 9;
$year = 2018;
$day = 1;
$firstday = new DateTime("$year-$month-1");
$dow = (int)$firstday->format('w');
$firstday->add(new DateInterval('P' . ((8 - $dow) % 7) . 'D'));
$weeknumber = $firstday->format('W');
echo $weeknumber ;

I think this code will do what you want. It first creates a DateTime object for the first of the month, then it moves that date forward to make it a Monday. Finally it prints the week of the year using format('W').
Edit
Updated code to print first Monday and week number for whole year
$year = 2018;
echo "Month | First Monday | Week\n";
for ($month = 1; $month <= 12; $month++) {
$firstday = DateTime::createFromFormat('Y-n-j', "$year-$month-1");
$dow = (int)$firstday->format('w');
// update to a monday (day 1)
$firstday->add(new DateInterval('P' . ((8 - $dow) % 7) . 'D'));
echo sprintf("%5d | %s | %4d\n", $month, $firstday->format('Y-m-d'), $firstday->format('W'));
}
Output:
Month | First Monday | Week
1 | 2018-01-01 | 1
2 | 2018-02-05 | 6
3 | 2018-03-05 | 10
4 | 2018-04-02 | 14
5 | 2018-05-07 | 19
6 | 2018-06-04 | 23
7 | 2018-07-02 | 27
8 | 2018-08-06 | 32
9 | 2018-09-03 | 36
10 | 2018-10-01 | 40
11 | 2018-11-05 | 45
12 | 2018-12-03 | 49

Related

Select and Group by fixed date interval

I'm working on a big MySQL time based statistic table.
I have a fixed time range (start and end date time objects) and get an interval string in ISO-8601 interval string like P1DT6H as PHP object where the start date in the range is also the start point of the interval and also defines the timezone used for the interval.
Now I want to select all data within the given time range grouped by this interval but I can't make it work even after lot of hours :(
For example I get a time range of 2015-09-01/2015-09-06 and an interval of P1DT6H and the following example table:
TIMESTAMP | count
2015-09-01 00:00:00 | 1
2015-09-01 02:00:00 | 1
2015-09-01 04:00:00 | 1
2015-09-01 06:00:00 | 1
2015-09-01 08:00:00 | 1
2015-09-01 10:00:00 | 1
2015-09-01 12:00:00 | 1
2015-09-01 14:00:00 | 1
2015-09-01 16:00:00 | 1
2015-09-01 18:00:00 | 1
2015-09-01 20:00:00 | 1
2015-09-01 22:00:00 | 1
2015-09-03 00:00:00 | 1
2015-09-03 02:00:00 | 1
2015-09-03 04:00:00 | 1
2015-09-03 06:00:00 | 1
2015-09-03 08:00:00 | 1
2015-09-03 10:00:00 | 1
2015-09-03 12:00:00 | 1
2015-09-03 14:00:00 | 1
2015-09-03 16:00:00 | 1
2015-09-03 18:00:00 | 1
2015-09-03 20:00:00 | 1
2015-09-03 22:00:00 | 1
2015-09-05 00:00:00 | 1
2015-09-05 02:00:00 | 1
2015-09-05 04:00:00 | 1
2015-09-05 06:00:00 | 1
2015-09-05 08:00:00 | 1
2015-09-05 10:00:00 | 1
2015-09-05 12:00:00 | 1
2015-09-05 14:00:00 | 1
2015-09-05 16:00:00 | 1
2015-09-05 18:00:00 | 1
2015-09-05 20:00:00 | 1
2015-09-05 22:00:00 | 1
With that I want to have the following result:
TIMESTAMP | count
2015-09-01 00:00:00 | 12
2015-09-02 06:00:00 | 6
2015-09-03 12:00:00 | 6
2015-09-04 18:00:00 | 12
For sure the interval can be more complicated, the time range can be very big and the data table is also a big table.
This needs to handle months where nearly every month have a different amount of days incl. leap year and also dst changes where a day can have 23, 24 or 25 hours. (Means a one day interval is different than a 24 hours interval)
It would be really really helpful if someone has a solution or can me point to the right direction for that kind of problem.
Thanks!
PS: I have a script that creates SQL an expression in base of a given db column, the start, end and interval objects but it only works for very simple intervals like P1D. I don't past it here as I don't want to ping all great brains into a non working direction that I already have ;)
What I have right now but it doesn't work with mixed intervals.
Examples:
Timezone handling:
if ($db->getTimezone()->getName() !== $start->getTimezone()->getName()) {
$col = 'CONVERT_TZ(' . $col
. ', ' . $this->quote($this->getTimezone()->getName())
. ', ' . $this->quote($start->getTimezone()->getName())
. ')';
}
P1M:
$m = ($interval->y * 12) + $interval->m;
if ($m) {
if ($m > 1) {
$mod = $start->format('Ym') % $m;
$mod = $mod ? ' + ' . $mod : '';
$expr = 'EXTRACT(YEAR_MONTH FROM ' . $col . ')';
$expr = $mod ? '(' . $expr . $mod . ')' : $expr;
$expr = ' - INTERVAL ' . $expr . ' % ' . $m . ' MONTH';
$sqlIntervalMonth = $expr;
}
$sqlIntervalDay = ' - INTERVAL DAY(' . $col . ') - 1 DAY';
if ($start->format('d') > 1) {
$sqlIntervalDay .= ' + INTERVAL ' . ($start->format('d') - 1) . ' DAY';
}
}
P1D:
$d = $interval->d;
if ($d) {
$days = $start->diff(new DateTime('0000-00-00'))->days;
$mod = $days % $d;
$mod = $mod ? ' + ' . $mod : '';
$expr = 'TO_DAYS(' . $col . ')';
$expr = $mod ? '(' . $expr . $mod . ')' : $expr;
$expr = ' - INTERVAL ' . $expr . ' % ' . $d . ' DAY';
$sqlIntervalDay = $expr;
}
EDIT 1: pointed out timezone, dst and leap year requirement.
EDIT 2: added PHP snippets
One idea is to convert the value of the time stamp to seconds and then round that value to the appropriate interval (36 hours in your case). Something like this:
select min(timestamp) as timestamp, sum(count)
from t
group by floor(to_seconds(timestamp) / 60 * 60 * 36) -- * 60 * 60 * 36
order by timestamp;
This uses the min() of the datetime value, because you seem to have that value in the table. Alternatively, you can convert the rounded seconds back to a datetime value.
This is the closest I could get. Though time periods without any data will not be represented (don't know if that is a problem or not):
select yourTimestamp,sum(yourCount)
from
(
select t.yourTimestamp,t.yourCount,
'2015-09-01' + interval (36*60)*(floor(timestampdiff(MINUTE,'2015-09-01',t.yourTimestamp)/(36*60))) minute as recordGrpTime
from t
where t.yourTimestamp between '2015-09-01' and '2015-09-06'
) t
group by recordGrpTime;

Change content of table according to week number

I am working on a script for a drivers license website, and I need to make a calendar like table for the students, so they can see when they have which lesson.
Right now we are updating the table manually, but I would like to make a script so it can do it automatically.
The table looks like this: (By the way, its a HTML table).
+----------+--------+---------+-----------+----------+--------+
| Week Nr. | Monday | Tuesday | Wednesday | Thursday | Friday |
+----------+--------+---------+-----------+----------+--------+
| 17 | 14 | 1 | 16 | 2 | |
+----------+--------+---------+-----------+----------+--------+
| 18 | 4 | 1 | 6 | | |
+----------+--------+---------+-----------+----------+--------+
| 19 | 8 | 1 | 11 | | |
+----------+--------+---------+-----------+----------+--------+
| 20 | 14 | 1 | 16 | 2 | |
+----------+--------+---------+-----------+----------+--------+
Lets say its this week (Week 17), it has its own set of lessons for every day, except Friday, which is the same for every week. Then it is the week after, which has its own set of lessons, and then it is 3 weeks after, which again has its own set of lessons. Then the 4th week, it start all over, with the same set as week 17, because its a 3 week program, over and over again.
What i want to do is that it automatically updates the table, so it shows the current week number. Then let us say that it is next week now, the table should have automatically update it self to show the current week and its set of lesson numbers.
The numbers under the column "Week Nr." are the week numbers, and the numbers under the day names are the lesson numbers.
So next week it should look like this:
+----------+--------+---------+-----------+----------+--------+
| Week Nr. | Monday | Tuesday | Wednesday | Thursday | Friday |
+----------+--------+---------+-----------+----------+--------+
| 18 | 4 | 1 | 6 | | |
+----------+--------+---------+-----------+----------+--------+
| 19 | 8 | 1 | 11 | | |
+----------+--------+---------+-----------+----------+--------+
| 20 | 14 | 1 | 16 | 2 | |
+----------+--------+---------+-----------+----------+--------+
| 21 | 4 | 1 | 6 | | |
+----------+--------+---------+-----------+----------+--------+
Is there anybody who could give me a hint on how to do that with PHP. I have tried everything I knkw, but I just cant get it right.
This is not exactly what you want, but it could be a good starting point. Just modify it to print out the HTML tags.
//Set a counter for the lessons
$j = 0;
//Loop through the weeks of the year
for ($i = 1; $i <= 52; $i++) {
echo "Week: ".$i."<br>";
echo "This weeks lessons: " . $j."<br>";
//Incrase counter
$j++;
if ($j % 3 === 0) {
//Reset counter if need
echo "<hr>";
$j = 0;
}
}

How to insert an irregular calendar events in mysql using PHP

I'm trying to enter events that occur over the same interval (Weekly, Bi-Monthly, Quarterly, Yearly). The script I'm showing is that of monthly..(If I can get that right, I can make an adaptation for the other intervals).
Events are entered along with the correct Week Number in which they occur.. But the following problem occur:
--- How can I make sure that months that has less than 31 days do not have events entered for them ?
----- If an event occurs on every 1st and 3rd friday (or whichever one), or last thursday of the month. How can I tweak the script below do do that.
Thank you.
A Sample of what I'm getting from mysql, when I insert...
+----+------+------+------------------+-----------+------------+----------+
| day| month| year | eventname | eventtime | eventplace | eventweek|
+----+------+------+------------------+-----------+------------+-----------
| 1 | 2 | 2011 | Social Gathering | 12PM | Room | 05 |
| 8 | 2 | 2011 | Social Gathering | 12PM | Room | 06 |
| 15| 2 | 2011 | Social Gathering | 12PM | Room | 07 |
| 22| 2 | 2011 | Social Gathering | 12PM | Room | 08 |
| 29| 2 | 2011 | Social Gathering | 12PM | Room | 09 |
+----+------+------+------------------+-----------+------------+----------+
PHP Code
<?php
if(isset($_POST['myform'])){
$day = array('1','2','3','4','5','6','7','8','9','10','11','12','13','14','15','16','17','18','19','20','21','22','23','24','25','26','27','28','29','30','31');
$month = array('1','2','3','4','5','6','7','8','9','10','11','12');
$year = array('2011', '2012','2013', '2014', '2015', '2016');
$startday = mysql_real_escape_string($_POST['day']);
$eventplace = mysql_real_escape_string($_POST['eventplace']);
$eventname = mysql_real_escape_string($_POST['eventname']);
$eventtime = mysql_real_escape_string($_POST['eventtime']);
for($i=0; $i<count($year); $i++){
for($j=0; $j<count($month); $j++){
for($k=$startday; $k<count($day); $k = $k + 7){
$date = mktime(0,0,0,$month[$j],$k,$year[$i]);
$week = date('W', $date) ;
$query = mysql_query(" INSERT INTO caldemo(day, month, year, eventname, eventtime, eventplace, eventweek)
VALUES ('".intval($k)."', '".intval($month[$j])."', '".intval($year[$i])."', '".$eventname."', '".$eventtime."', '".$eventplace."', '".intval($week)."' )")or die(mysql_error()) ;
}
}
}
}
?>
Simple php solution:
function setDatePeriod($months=1, $date='')
{
if(!$date) $date = date('Y-m-d');
$d = new DateTime( $date );
$d->modify( "+{$months} months" );
return $d->format('Y-m-d');
}
echo setDatePeriod(3);

Determine if the store is open?

In PHP and MySQL - how to determine if the Store is Open or Close (return true or false)?
Also how to get the next opening hours if the store is closed?
Example of Opening_Hours table:
+----+---------+----------+-----------+------------+---------+
| id | shop_id | week_day | open_hour | close_hour | enabled |
+----+---------+----------+-----------+------------+---------+
| 1 | 1 | 1 | 16:30:00 | 23:30:00 | 1 |
| 2 | 1 | 2 | 16:30:00 | 23:30:00 | 1 |
| 3 | 1 | 3 | 16:30:00 | 23:30:00 | 0 |
| 4 | 1 | 4 | 16:30:00 | 23:30:00 | 1 |
| 5 | 1 | 5 | 10:00:00 | 13:00:00 | 1 |
| 6 | 1 | 5 | 17:15:00 | 00:30:00 | 1 |
| 7 | 1 | 6 | 17:15:00 | 01:30:00 | 1 |
| 8 | 1 | 7 | 16:30:00 | 23:30:00 | 0 |
+----+---------+----------+-----------+------------+---------+
The open_hour and close_hour are TIME type fields. Table design ok?
Example of current times:
Current time: Tue 23:00, - Output: Open, 'Open at Tue 16:30 - 23:30'
Current time: Tue 23:40, - Output: Close, 'Open at Thur 16:30 - 23:30'
Open on Thursday because Opening_Hours.week_day = 3 is disabled
Now how to handle the midnight time? This get more complicated.
As you can see, on Saturday (Opening_Hours.week_day = 5), it is open from 17:15 PM to 01:30 (closed next day Sunday)
If the current time is Sunday 01:15 AM, then the store would still be open base on Opening_Hours.week_day = 5.
Output: Open, 'Open at Sat 17:15 - 01:30'
In the past, I've handled this by using a time stamp without a date (seconds since midnight). So for Saturday, the open would be 62100 and the close would be 91800.
My thought was this removes some of the logic needed when a close crosses midnight, as you only need to compare the seconds since the start of the date to the time range.
And it's pretty easy to check if it's still open from 'yesterday' - just add 86400 to the current 'time' (seconds since the start of the day) and check against the previous day.
Probably all a single SQL statement.
You can use the PHP date() function and compare it to your opening hours.
You can do something like this recursive function (not working PHP code, but PHP combined with pseudo-code):
/* $current_time should be in the format of date("His") */
function check_hours($current_day, $current_time)
{
Get the MySQL row for today here
if (Opening_Hours.enabled == 1 WHERE Opening_Hours.week_day == $current_day)
{
if ((date("His") >= Opening_Hours.open_hour) and ($current_time <= Opening_Hours.close_hour))
{
// convert_numeric_day_to_full_representation isn't a real function! make one
return 'Open: ' . convert_numeric_day_to_full_representation($current_day) . ' ' . Opening_Hours.open_hour . ' – ' . Opening_Hours.close_hour;
}
elseif (date("His") < Opening_Hours.open_hour)
{
return 'Closed: Next opening hours: ' . convert_numeric_day_to_full_representation($current_day) . ' ' . Opening_Hours.open_hour . ' – ' . Opening_Hours.close_hour;
}
else
{
return check_hours($tomorrow, '000000');
}
}
else
{
return check_hours($tomorrow, '000000');
}
}

Bonkers PHP Months?

Here is a basic proof-of-concept script:
<?php
for($i = 1; $i < 13; $i++)
{
echo 'Using ' . $i . ' | ';
echo date('F', mktime(0,0,0,$i)) . " | ";
echo date('F', strtotime('2011-' . $i . '-01')) . "<br />";
}
And the output I get is:
Using 1 | January | January
Using 2 | March | February
Using 3 | March | March
Using 4 | April | April
Using 5 | May | May
Using 6 | June | June
Using 7 | July | July
Using 8 | August | August
Using 9 | September | September
Using 10 | October | October
Using 11 | November | November
Using 12 | December | December
What happened to February??
This is killing me as it just stopped showing February and started showing March.
You are using mktime() incorrectly.
int mktime ([ int $hour = date("H")
[, int $minute = date("i")
[, int $second = date("s")
[, int $month = date("n")
[, int $day = date("j") <------------ here
[, int $year = date("Y") <------------ and here
[, int $is_dst = -1 ]]]]]]] )
If you don't specify $day and $year, they will default to today's date.
Today is the 30th, which doesn't exist in February.
This will work:
echo date('F', mktime(0,0,0,$i,1,2011)) . " | ";
Quite simple - you're running this on the 29th, 30th, or 31st of the month. mktime(0,0,0,2) is really mktime(0,0,0,2,date('j'),date('Y')), which in the case of today would try to create February 30th 2011, which is March 2nd.
From the manual:
Arguments may be left out in order
from right to left; any arguments thus
omitted will be set to the current
value according to the local date and
time.
Thus, it sets the fifth argument to the current day (30 here). Which means it adds to the date, since 30 is an invalid day in February, and makes it march.
See this: http://www.php.net/manual/en/function.mktime.php#77490

Categories