- Feature Articles
- CodeSOD
- Error'd
- Forums
-
Other Articles
- Random Article
- Other Series
- Alex's Soapbox
- Announcements
- Best of…
- Best of Email
- Best of the Sidebar
- Bring Your Own Code
- Coded Smorgasbord
- Mandatory Fun Day
- Off Topic
- Representative Line
- News Roundup
- Editor's Soapbox
- Software on the Rocks
- Souvenir Potpourri
- Sponsor Post
- Tales from the Interview
- The Daily WTF: Live
- Virtudyne
Admin
$theFrist
Ftfy.
Admin
I expect the "weird feb issue" was how to deal with questions like "what date is one calendar month before 31 March?".
Admin
0 March.
https://en.wikipedia.org/wiki/List_of_non-standard_dates#March_0
Admin
"Weird Feb" was a guy in accounting who had an issue with herpes.
Admin
So, where's the WTF? PHP dev not reading yhe language documentation? That stuff happens more than cache misses.
Admin
Today I learned! This was an interesting read; thank you for sharing!
Admin
There are three hard things in software development: naming things, date handling and off by one errors.
Admin
Argh, two things.
Admin
An off-by-one error in the stock off-by-one-error joke. Brillant! It's been a while since I've had such a good laugh on this site.
Admin
Date arithmetic can be a total bastard for other reasons. Having worked with things like defined benefit pensions "months" and "years" aren't what we might think they are, they are what the actuary says they are (subsequently amended by whatever the last court case ruled). You simply can't assume a year is 365 days, or 365.25 days, or what it really is, without checking ... same for a month. And it is not going to be consistent within any given calculation, let alone chunk of code.
If something looks wrong, it probably isn't, it just could probably do with better variable/constant names. Although as half the test cases contradict each other you can never be sure it's right.
Granted, I'm sure most of these date WTFs are because an inexperienced coder didn't know or trust the inbuilt date libraries, or maybe an experienced one who never forgave java.util.Date or something, but I've had to hand craft stuff a lot because "under these circumstances the leap day is not applied unless blah blah blah", for instance.
Admin
The simplest fix is probably: 'date("Y-m", strtotime("first day of now - 1 month"))'. This works, whether leap year or not and also at the beginning of the year.
Admin
The problem can be sen with: echo date("Y-m-d", strtotime("-1 month", strtotime("2020-03-31")));
A possible WTF fix is: echo date("Y-m-d", strtotime("-1 month", strtotime(date("Y-m-01", strtotime("2020-03-31")))));
Admin
strtotime is a complex and delicate creature. It has been subject to many subtle (and buggy) changes over time. It will do its best : in the absence of any actual time it assumes NOW, and parses the inputted parameter to "calculate" a relative date (the current version automatically applies DST and whatever timezone is in effect - well, it does for the version I'm using! And that can be a serious PITA when I'm manipulating DATETIME). So "date('Y-m', strtotime('-1 month'))" will give you this day, last month (effectively). The "weird feb" thing might have been because of issues around its awareness and handling of leap years.
There are lots of W(hy)TF's in this code snippet, but there is little or no mystery to the logic behind "...The “fix” is to prepend a “0” to the front of the dates...". Yes, the returned, formatted, month will be "01", "02",,, "12" etc and there are a million and one reasons as to why I (or anybody else) would want this. That "$date->format('m')-1" works is a benefit / curse / abuse / elegant / etc / etc of all that is holy about ... whatever. The fact remains that it is an arithmetic operation on a string and if you ask PHP to subtract 1 from "02" it will give you 1 (we will quietly ignore what happens if you subtract 1 from "01" or 2 from "02" etc).
Like I said, there are many (major and minor) WTF's here ...
Admin
I remeber cache invalidation as the second hard thing to do. Maybe we have three hard things now?
I worked with date for many years with historic time zones. What was the time difference between GMT and Riad between 1984-1988. 3 hours and 7 minutes. before and after it was just 3 hours!
Always keep time/date as system type until you need to display it. Then use local display.
Admin
If what I'm heard is correct Julius Cesar changed July to contain 31 days by remove one from February. Augustus did the same with August month to get the same status as Cesar
Admin
I'll never understand why people don't just use first day of and last day of.
It's a really simple solution that avoids the need for messing around when we don't care about the day and it doesn't have horrible problems with PHP trying to work out the 31st of February or whatever.
Admin
For example because of "banker's years", which have 12 months with 30 days each. "Because it's easier to calculate interest this way."
Admin
Another WTF is that the block of code after the Feb issue comment overwrites all the $theXXXMonth variables that were set above, so there was no reason for all that formatting and splitting.
Admin
Yeah, that is what I see as really strange. The progression from good to bad code.
First it does the job almost right:
$theFirst = date("Y-m", strtotime("-1 months"));
Then it adds in something strange and pointless:
list($theFirstYear, $theFirstMonth) = explode('-', $theFirst);
$dateArray = array( ... ,$theFirstYear.'-'.$theFirstMonth);
And finally it gets overwritten to do something completely bizarre.
$date = new DateTime();
$theFirstMonth = $date->format('m')-1;
if(strlen($theFirstMonth) < 2){
}
Admin
Every time I see a PHP article, I know there are going to be a lot of people commenting who don't understand the language.
All versions of this code are buggy. Here's why:
The original code is the first block. This doesn't work because months have different days. "March 30th minus one month" is February 30, which doesn't exist, so you get March 1 (in a leap year) or March 2nd (in a non-leap year), which is the appropriate number of days after the last day of the month that does exist. Note that this isn't strictly a February issue; if you ask for one month before May 31st, it will tell you May 1.
Because of this, they changed it to try to get the month and subtract one. It makes a date, gets the numeric month value, and subtracts from it. Adding the zero on makes perfect sense, because whether you get the month as "01" or "1", you're getting a string, and once you subtract an integer from a string, you're left with an integer, so you need to add the zero back. What this code misses is that when it comes to months, 1-1 is 12, not 0, and 1-2 is 11, not -1, and so on. The line should really something like:
$theFirstMonth = ($date->format('m')-2+12)%12+1;
You want to subtract a month, but you want a result from 1-12, not 0,11, so you're going to add 1, so subtract 2, not 1. Then add 12, in case the number is negative, then modulo it, then add the 1 back in to correct the range back to 1-12 from 0-11.
Or a more sane version that's longer:
Either way, add the leading zero back after this.
Admin
Sorry, $date->format, not $date_format above.
Admin
To be honest, I'm a little surprised it keeps track of the fact that it's on "February 30th" long enough that "first day of" actually returns the right month.
Admin
Yeah, there's a lot of historic stuff in here. Not working? Completely rewrite the logic but leave the old code in there just in case!
Admin
Please don't leave old code around. That's what source control is for.
Admin
I'm a little surprised you assume first day is applied after -1 month.
Admin
Shut the fuck up
Admin
Dates are hard; Printing a formatted string containing just numbers should not be, but in Fortran it is. (Or at least, the format specifier syntax makes it hard to read.)
Admin
Wanna see something interesting? Guess what each of these makes:
echo date('Y-m-d', strtotime('+4 weeks'), "\n"; echo date('Y-m-d', strtotime('first day of'), "\n"; echo date('Y-m-d', strtotime('first day of +4 weeks'), "\n";
Admin
Nyooooo math, nyo-ho-ho-hoooo math: https://www.youtube.com/watch?v=UIKGV2cTgqA
Anyway, I'm disappointed there wasn't a "the leading 0 causes the number to be interpreted as octal, hijinx ensue" part to this.
Admin
Assuming the brackets are fixed then yes you get unexpected results if you assume the order of inputs to matter.
strtotime
does modifications to existing parts of the date in order, then applies "first day of", not the other way around. Effectively it's doing this:What does work if you want to mess with this sort of thing is modification of other parts that would change the day like hours or minutes
Although honestly if you're looking for the first of the month + a given number of days or weeks you should probably write it taking into account that you already know what day of the month you want and maybe should use something like mktime instead.
Admin
"Date arithmetic can be a total bastard for other reasons."
Not to mention that fact that if you go back far enough, there was a several hundred year period in which the world did not agree on what date it was.
Admin
cool
Addendum 2022-12-27 23:26: I know so many people who face the problem of finding a partner. But more often than not, it's people who are unconventional, like transgender people. I can help them and tell them what to do. For example they can look and read asian dating sites in america where they can really find tgirl hookup and start communicating, making friends, getting acquainted and so on. I for example have done all this already and I am very satisfied that I have succeeded. I hope I was able to help you and was really helpful. Good luck with that.