Logical Query to calculate weeks - php

I ask user to enter start and end date in a certain application. Then I calculate the no. of weeks in between these two dates.
I want to fetch documents created per week in the given period of time.
I am unable to implement a logic which will help me to fetch first week, second week, third week, and so on.
I will use this as input to database and then create graph. I am using php as the server side language. Anyone could suggest me the Algorithm.
ex:
Start date: 20/07/2012
End Date: 19/02/2013.
Total no. of days: 214.
Total no. of weeks: 30 (30 weeks and 4 days)
I want to fetch period of 20/07/2012 to 27/07/2012 and no. of Docs during this period. Till 15/02/2013.

Without seeing your database structure here is a sample of what you require
SELECT YEAR(doc_created) AS report_year, WEEKOFYEAR(doc_created) AS report_week, COUNT(*) AS doc_count
FROM documents
WHERE doc_created BETWEEN '2012-07-20' AND '2013-07-19'
GROUP BY YEAR(doc_created), WEEKOFYEAR(doc_created)
grouping by weekofyear is not enough, as period may overlap the next year, so we should also include the year.
possible results:
year week docs
2012 1 4
2012 3 1
2013 1 65
2013 2 4
as you can see 2012 week 1 would overlap 2013 week 1, if we just used week number.
for your grid/graph use the reference (year wk) and amount (docs)
e.g. 2012wk1 is 4, 2012wk3 is 1

Try this code:
$start_date = "20-07-2012";
$end_date = "20-08-2012 ";
while($start_date){
if(strtotime($start_date) > strtotime($end_date)){
exit;
}
$start_date = strtotime("+7 day", strtotime($start_date));
$start_date = date("d-m-Y", $start_date);
echo $start_date;
echo "<br/>";
}

Related

is there any way to keep the month same?

I have a condition in laravel where I have to put a min date on html input type date but the condition is complex.
Condition :
1 : User should only be able to select date from past ten days.
2 : Only two days from previous month. Example lets today date is 4 april then the user should
only be able to select from 4 april to down 1 april and 2 days previous month.
so I can put the min="some date" in input of date
You didn't specify how you actually set the date, but here is a PHP version that should get you closer. All you need to do is extract the parts you need from $minDate.
$lastTwo = new DateTime(date('Y-m-d', strtotime(date('Y-m-1') . ' -2 days')));
$lastTen = new DateTime(date('Y-m-d', strtotime('-10 days')));
$minDate = max($lastTen, $lastTwo);
Use Carbon::now()->month; to get current month and make conditon according to your query.

How do I find date ranges given a certain week number and year? [duplicate]

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.

Quirk with PHP DateTime ISO weeks

I have 3 values:
$timezone = new \DateTimeZone('America/New_York');
$year = 2019;
$week = 52;
I then take these 3 values and run it through a script:
$nowTime = new \DateTime('now', $timezone);
$currTime = clone $nowTime;
$currTime->setISODate($year, $week, 1);
$currTime->setTime(0,0,0);
As you can see, I am setting the current time to be the beginning of Week 52 in 2019.
I am then trying to get information about the next week.
$nextTime = clone $currTime;
$nextTime->modify('+1 week');
$nextWeek = [
'year' => $nextTime->format('Y'),
'week' => $nextTime->format('W'),
];
This script has worked in almost every instance I have found...
Hopever, in Week 52 in 2019, instead of returning the next week as Week 1 in 2020, it returns the next week as Week 1 in 2019... which sends me backwards in time.
How do I fix this? This seems to happen in every year where there are 53 weeks in the year.
You're combining two date formats (Y and W) that don't make sense together. W is the ISO week number, but Y is the calendar year.
The first ISO week of 2020 starts on December 30, 2019, so for that date, W returns 1, but Y still refers to the calendar year 2019.
PHP offers the o date modifier that can be used in place of Y in your code, defined in the manual as:
ISO-8601 week-numbering year. This has the same value as Y, except that if the ISO week number (W) belongs to the previous or next year, that year is used instead. (added in PHP 5.1.0)
So you can change your code to
$nextWeek = [
'year' => $nextTime->format('o'),
'week' => $nextTime->format('W'),
];
and it should work as intended.
There are 2 different ways how weeks can be handled, depending on the task.
1. ISO format:
Weeks start with Monday. Each week's year is the Gregorian year in
which the Thursday falls. The first week of the year, hence, always
contains 4 January. ISO week year numbering therefore slightly
deviates from the Gregorian for some days close to 1 January.
These rules may be hard to handle manually, that's why it's a part of standard PHP, so you can just use 'week' => $nextTime->format('W')
It is indeed possible that a day in 2019 will belong to a week from 2020. And it's easy to prove: when you open a calendar for 2019 / December, you may notice that last week "may share" days from next year. To prevent a problem with overlapping, when the same week belongs to different years but its number is different, e.g. week 52 in a year 2019 is the same as week 1 in a year 2020, they decided to make a set of rules: ISO. These rules are especially useful in accounting to prevent "ambiguous weeks".
2. You only need a "mathematical" week number as a simple counter:
$nextWeek = [
'year' => $nextTime->format('Y'),
'week' => (int)(($nextTime->format('z')) / 7) + 1
];
z formatter is The day of the year (starting from 0) and that's why I am adding "+1" at the end.
Even though it may look as a good approach, it has a drawback: the week #52 in 2019 is the same as week #1 in 2020.

Last day of the leap year, week 53 or 1?

I have a script that process raw CSV data and generate report grouped by week of the year.
Which looks something like this:
//timezone is set to Europe/London
$date = new DateTime($raw['order_date']); // example: 12/31/2012
$key = $date->format('Y W'); // 2012 01
$array[$key][] = $raw['product_id'];
Everything was working fine until I tried to parse data generated over new year eve, for some reason system believes that 31 December 2012 is week number 1 of year 2012.
I'm not sure is it bug or a feature, but produced reports are definitely wrong.
What is a correct way of passing this issue and keeping data grouped by weeks?
Try this:
$key = $date->format('o W');
I think the week is defined Thursday, meaning if the Thursday falls in 2013, then it's counted as being a week of that year.
$w=(int)date('W');
$m=(int)date('n');
$w=$w==1?($m==12?53:1):($w>=51?($m==1?0:$w):$w);
$year = date('Y');
if($w==53)
{
$year=$year+1;
}
past year i am getting all d records properly but in 2016 april first select than I got april 2015 report show any thing missing or its leap year problem

March 14th not 86400 seconds long?

In my web application, I have users input a date in a simple textbox. That input (after being sanitized, of course), is run through strtotime(), and 86399 is added to it, to make that timestamp the end of the day written (11:59:59). This is for due date purposes (so if the date passes, the application raises a flag)
For the days I tested, it worked...
January 5th saved as january 5th, at the end of the day.
March 13th saved as March 13th
March 15th saved as March 15th
March 14th, for whatever reason, saved itself as March 15th.
Is March 14th mysteriously a couple seconds short or something??
Update: Thanks to oezi for the solution - worked like a charm. Code as requested:
Old code:
if ($_POST['dateto'] != '') {
$dateto = strtotime(mysql_real_escape_string($_POST['dateto'])) + 86399;
}
New code:
# Offset to "end of day"
list($y,$m,$d) = explode('-',date("Y-m-d",strtotime($_POST['dateto'])));
$d++;
$dateto = strtotime($y . '-' . $m . '-' . $d) - 1;
March 14, 2010 is the day Daylight Saving Time begins in the United States. So if you're doing math in the local time zone, March 14 is only 23 hours long.
I would assume because this is the beginning of daylight savings time
Like others said, this is because of daylight saving time. To solve this problem, you could do this:
<?php
list($y,$m,$d) = explode('-',date("Y-m-d",strtotime($date_from_user)));
$h = 23;
$i = 59;
$s = 59;
$mytimestamp = "$y-$m-$d $h:$i:$s";
?>
What database are you using? there has to be a better way to do this (most date manipulation commands are database specific). In SQL Server, I'd just add 1 day to the date and then subtract 1 second:
DECLARE #YourDate datetime
SET #YourDate='2010-03-14'
SELECT DATEADD(ss,-1,#YourDate+1)
OUTPUT:
-----------------------
2010-03-14 23:59:59.000
(1 row(s) affected)
for what it is worth, I'd much prefer to have a condition: < NextDay than <=CurrentDay12_59_59
In all time zones that "support" daylight savings time, you'll get two days a year that don't have 24h. They'll have 25h or 23h respectively. And don't even think of hardcoding those dates. They change every year, and between time zones.
Oh, and here's a list of 34 other reasons that you hadn't thought about, and why you shouldn't do what you're doing.
http://tycho.usno.navy.mil/leapsec.html
Not all days are 86400 seconds long.
This is a rare event. And (historically) never scheduled in March.

Categories