I need to calculate the number of the week following a given week. This is trivial for most weeks within the year, but not at the end / beginning of the year. For example if I need to know the week following week 52 of 2013.
I would like to use the defaul_week_format 3, i.e.
a) the weeks start with Monday (instead of Sunday)
b) the numbering within a year starts with 1 (instead of 0)
and c) week number 1 is the first week with more than 3 days this year.
My approach to e.g. calculate the week after week 36 2014 is the following:
SELECT WEEK(DATE_ADD(STR_TO_DATE('W36 2014 Tuesday', 'W%V %X %W'), INTERVAL 1 WEEK))
For this example I calculate the date of Tuesday in week 36, add one week, and calculate the week of this day. This would work, but even without adding one week, I have this strange behaviour:
It works for the default_week_format 0:
SET ##local.default_week_format=0;
SELECT STR_TO_DATE('W36 2014 Tuesday', 'W%V %X %W');
-> Tuesday of week 36 is 2014-09-09
SELECT week('2014-09-09');
-> 2014-09-09 is in week 36
So far, so good: Tuesday of week 36 is in week 36.
But this simple experiment does NOT work for default_week_format 3:
SET ##local.default_week_format=3;
SELECT STR_TO_DATE('W36 2014 Tuesday', 'W%V %X %W');
-> Tuesday of week 36 is 2014-09-09
-> This is wrong, because numbering should start with 1 (instead of 0 now)!
-> Tuesday of week 36 should be 2014-09-02
SELECT week('2014-09-09');
-> 2014-09-09 is in week 37
So MySQL tells me that Tuesday of week 36 is in week 37!
My only explanation for this:
week() takes default_week_format into account
str_to_date() ignores the default_week_format
How can I force MySQL function str_to_date to use the default_week_format?
Or: How else can I calculate the number of the following week?
I could also do it in PHP, but I get the weeks' numbers from a MySQL database.
Thanks for any help!
I was facing exactly the same problem. My solution - perhaps not the greatest one, but it works.
As you already mentionned: Most of the cases are trivial, you just need to know the year end / beginning. Therefore, I just store the relevant weeks for the needed number of years in the following table:
CREATE TABLE `NEXT_WEEK_TAB` (
`CUR_WEEK` varchar(8) NOT NULL,
`NEXT_WEEK` varchar(8) NOT NULL,
PRIMARY KEY (`CUR_WEEK`,`NEXT_WEEK`)
)
You get the following week now with the current algorithm:
following_week = (SELECT next_week
FROM next_week_tab
WHERE cur_week = <your_current_week>);
if !following_week then following_week++;
As I said: Probably not the nicest solution, but it's pretty simple - and it works.
I think you must use Week with a mode argument
mysql> SELECT WEEK('2008-02-20',0);
-> 7
mysql> SELECT WEEK('2008-02-20',1);
-> 8
take a look here :
http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_week
Related
I have the following example of me subtracting the DateInterval from DateTimeImmutable
$dateA = new DateTimeImmutable('2016-06-30');
$dateB = new DateTimeImmutable('2016-05-31');
$dateInterval = new DateInterval('P3M');
// print 2016-03-30 as expected
echo $dateA->sub($dateInterval)->format('Y-m-d');
// print 2016-03-02 which i would expect 2016-02-29
echo $dateB->sub($dateInterval)->format('Y-m-d');
When I set the period to 'P8M' it works as expected. How it comes, it dosent works for february?
Ok, it's really simple (kind of). Each 'month' interval evaluates to the prior (or X number of prior) month's equivalent day. If there are more days in the current month, than the month being landed on, the excess overflows to the following month.
So if you have a date which is May 31, 2016 and want to subtract 3 month intervals, it will:
Go back 3 months (in the list of months, don't think days yet), resulting in 'February'
Then look for February 31st. This doesn't exist so bleed over to following month 2 days (2016 Febuary has 29 days, so 2 extra days)
Viola! March 2nd.
Go forward, lets say you're in May 31, 2016 and want to add one month
Go forward one month to June.
Look for June 31st, nope, 1 extra day, bleed over to July.
As expected, July 1st is the answer.
The lesson in this: Adding and Subtracting Month intervals sucks, is confusing, and can lead to non-intuitive results unless you've got your month calculation rosetta stone with you.
Explanation from the PHP Docs
Note:
Relative month values are calculated based on the length of months that they pass through. An example would be "+2 month 2011-11-30", which would produce "2012-01-30". This is due to November being 30 days in length, and December being 31 days in length, producing a total of 61 days.
OK so i have this query:
SELECT obrero as MAESTRO, sum(costo_semanal) AS TOTAL_COST,
ROUND(SUM(week_cost)/MONTH(CURDATE()),2) AS MONTHLY_COST,
ROUND(SUM(week_cost)/WEEK(CURDATE()),2) AS WEEKLY_COST
from tbl_costos WHERE obrero ='$maestro'
I did this and it worked great in 2015, the problem is that now on 2016 we go back to week 1 and month 1 so im not having the proper division.
What I need to accomplish is to sum the 52 weeks of the past year and sum the current week of this year so i could have a % of the cost per week
"cost/number of weeks" = $cost per week.
for example of today 2016-01-18 being the 4th week of the year
total paid (of 2015 and 4 weeks of 2016) = $4000.00
weeks = 52 + 4 = 56
4000.00/56 = $71.4285714 average cost per week
The same thing applies to Months, it should be doing the division with 13, and cus January is month 1, its doing it over 1.
I could just do:
SUM(week_cost)/(12+ MONTH(CURDATE()));
and
SUM(week_cost)/(52 + WEEK(CURDATE()));
but that would solve the problem for this year only!!
You should use DATEDIFF() in order to calculate the number of days each maestro has worked from a given date, "start_date" to a given end date "end_date", and then convert those days to weeks, months and years if you need to.
Be flexible and anticipate that each maestro can work from any given date, or a report can be asked from any given date. Your's assume that each maestro started to work on 2015-01-01 and that all reports shall be done with this in mind. Reality is different.
Select obrero as MAESTRO, sum(costo_semanal) as TOTAL_COST, ROUND(SUM(costo_semanal/ROUND(DATEDIFF(start_date, end_date)/30,0)),0) AS MONTHLY_COST, ROUND(SUM(costo_semanal/ROUND(DATEDIFF(start_date, end_date)/7,0)),0) AS WEEKLY_COST FROM tbl_costos WHERE obrero=$maestro;
Do not place the variable $maestro on your query, better use PREPARED STATEMENTS.
I am trying to add a month to a date in posgresql, while setting DAY to the last day of the month.
How?
An example
UPDATE temp
SET expiration_date = expiration_date + interval '1' month
WHERE name = 'xxx'
The thing is, that if date was 2014-04-30 for example, it will add one month, and date will become 2014-05-30, and May does have 31 days.
Examples of what i want to accomplish
2014-04-30 + 1 month -> 2014-05-31
2014-05-31 + 1 month -> 2014-06-30
Need some tips on that. Is it possible in postgres? I could use PHP to count it, but I would love to avoid that.
If I understand you correctly, you want a last day of the following month. This can be done like this:
SELECT date_trunc('mon','2014-04-30'::date+interval'2mon')-interval'1day',
date_trunc('mon','2014-05-31'::date+interval'2mon')-interval'1day';
I have a question and can't find that specific answer.
In my application, my work year start on july 1 every years. So 52 weeks later, I start again on july first. What I want is a field that I enter let say week 32. I want to have the answer of what is the first day of that specified week and show it as date format. So in other words, if I put week 1 in the field, it will give me the result = July 1 and if I put Week 2 in the field, it will gives me july 8, etc. But I think that every year could change. So I need a calculation that will do this. Is it possible in php?
Tks for help
Seby
strtotime("July 1 2013 +".$monthNum." months");
something like this?
As the headline says, PHP's date("W") function gives back the calendar week (for the current day). Unfortunatly it gives back 52 or 53 for the first day(s) of most years. This is, in a simple thinking way, correct, but very annoying, as January 1st of 2012 is not calendar week 52, it's NOT a calendar week of the current year. Most calendars define this as week 0 or week 52 of the previous year.
This is very tricky when you group each day of the year by their calendar week: 1st of January 2012 and 31st of December 2012 are both put into the same calendar week group.
So my question is: Is there a (native) year-sensitive alternative to PHP's date("W") ?
EDIT: I think I wrote the first version of this question in a very unclear way, so this is my edit: I'm searching for a function that gives back the correct calendar week for the first day(s) of the year. PHP's date("W") gives back 52 for the 1st of January 2012, which is "wrong". It should be 0 or null. According to official sources, the first calendar week of a year starts on the first monday of the year. So, if the first day of a year is not a monday, it's not week 1 ! It's week 0. The wikipedia article says
If 1 January is on a Monday, Tuesday, Wednesday or Thursday, it is in week 01. If 1 January is on a Friday, Saturday or Sunday, it is in week 52 or 53 of the previous year.
This becomes tricky as the last days of the year are also in week 52/53. date("W") does not divide into current year and previous year.
This solution converts the excess of december to week 53 and everything in january prior to week 1 to week 0.
$w=(int)date('W');
$m=(int)date('n');
$w=$w==1?($m==12?53:1):($w>=51?($m==1?0:$w):$w);
echo "week $w in ".date('Y');
2013-12-31 ==> week 53 in 2013
2014-01-01 ==> week 1 in 2014
2015-12-31 ==> week 52 in 2015
2016-01-01 ==> week 0 in 2016
And a small test run, so you can see for yourself ;-)
$id=array(25,26,27,28,29,30,31,1,2,3,4,5,6,7,8);
for($iy=2013;$iy<2067;++$iy){foreach($id as $k=>$v){if($k<7){$im=12;}else{$im=1;}
if($k==7){++$iy;echo '====<br>';}$tme=strtotime("$im/$v/$iy");
echo date('d-m-Y',$tme),' * * ';
//THE ACTUAL CODE =================
$w=(int)date('W',$tme);
$m=(int)date('n',$tme);
$w=$w==1?($m==12?53:1):($w>=51?($m==1?0:$w):$w);
//THE ACTUAL CODE =================
echo '<b>WEEK: ',$w,' --- ','YEAR: ',date('Y',$tme),'</b><br>';}--$iy;
echo '----------------------------------<br>';}
Is there a (native) year-sensitive alternative to PHP's date("W") ?
No, there isn't.
According to official sources, the first calendar week of a year starts on the first monday of the year.
I'm not sure what official sources you're referring to.
PHP's date("W") returns the week number according to ISO 8601. As an international standard, ISO 8601 counts as one of possibly many "official sources". If its definition of week numbers doesn't fit your application, you're free to use anything else you like.
If you use a non-standard definition of "first week of the year", or if you use an official source that's not widely recognized, expect to have to write your own function to replace date("W"). (I'm pretty sure you'll need to write a function.)
The date 2012-01-01 was a Sunday. ISO 8601, Wikipedia, and php agree that the ISO week number for 2012-01-01 is 52.
ISO 8601 doesn't define a week 0.
So, if the first day of a year is not a monday, it's not week 1 !
Neither ISO nor Wikipedia say that. ISO 8601 defines week number 1 as the week that has the year's first Thursday in it. For 2012, the first Thursday was on Jan 5, so week number 1 was Jan 2 to Jan 8. 2012-01-01 was in the final week of the previous year, in terms of ISO weeks.
If you want something different, you can play with arithmetic, division, and so on. (Try dividing date("z") by 7, for example.) Or you can store that data in a database, and have your weeks any way you like.
If you're dealing with accounting periods, I'd almost certainly store that data in a table in a database. It's pretty easy to generate that kind of data with a spreadsheet.
The text of data in a table is much easier to audit than the text of a php function, no matter how simple that function is. And the data is certain to be the same for any program that accesses it, no matter what language it's written in. (So if your database someday has programs written in 5 different languages accessing it, you don't have to write, test, and maintain 5 different functions to get the week number.)
$d = new DateTime('first monday january '.date('Y'));
echo $d->format("W");
Google brought me here, and I wanted to post the following to help others like me...
I am in the US, and use DayPilot, and it works as follows:
Week starts on Sun, not Mon.
Jan 1st is always Week 1.
If Jan 1st is not a Sunday, Week 1 is less than 7 days.
This all makes a lot of since to me!
Here is my PHP function to copy that behavior:
function ProperWeekNum($inDate)
{$outNum = $inDate->format('W');
//Make week start on Sunday
if ($inDate->format('D') == 'Sun') {$outNum++;}
//Fix begining of year
if (($outNum >= 52) && ($inDate->format('M') == 'Jan')) {$outNum = 1;}
//Fix WEEK #1 is 1-day (Sat)
else //...without this 2022 was off by 1 all year
{$jan1st = new DateTime($inDate->format('Y').'-01-01');
if ($jan1st->format('D') == 'Sat') {$outNum++;}
}
//Return without leading zero
return ltrim($outNum, '0');
}
I use the function as follows, so when I click on DayPilot, my custom popup's Week # always matches DayPilot's Week #:
$weeknum = ProperWeekNum($startdate);
if ($weeknum != ProperWeekNum($enddate))
{$weeknum .= '-'.ProperWeekNum($enddate);}
Probably won't help the OP, but hopefully it helps someone.