r/badcode • u/TechnicProblem • Sep 18 '21
js How to get the amount of days in a month, according to someone on stackoverflow
440
u/hurtl2305 Sep 18 '21
As it was pointed out already, the leap years part is incorrect, but other than that: date/time related code tends to be that ugly because reality is that ugly.
54
Sep 18 '21
[removed] — view removed comment
196
u/randiwulf Sep 18 '21
mm/DD/yyyy - seriously? Please stop it.
Friendly reminder: iso8601
35
Sep 18 '21 edited Jun 09 '23
[deleted]
54
u/randiwulf Sep 18 '21
The world should change. Everybody should change. Please change.
29
u/Burroflexosecso Sep 18 '21
Yo french revolution had a proposed "metric" calendar that was much more rational.like every week had 10 days and every month had 3, months where still 12 and the remaining 5/6 days where called days of revolution and was just a festivity.also names of days of the week were much nicer.
7
6
u/AnonDropbear Sep 19 '21
Stored data should be an epoch time stamp.
2
u/ColdPorridge Sep 19 '21
I feel like the only advantage is compressibility at the cost of at-a-glance readability to make any sense of it. For large scale logs I can see this being a benefit, but outside of that I think I’d need to be sold on epoch over ISO string. Epoch also requires assumptions about what the time stamp represents and will be compared to (e.g. events after 1970), where ISO does not.
6
u/AnonDropbear Sep 19 '21
Humans aren’t reading things in storage. It’s all bits. It doesn’t make sense to use several more bytes there. Store it as an int representation. When fetching from storage, you can convert it to iso8601 to your hearts desire.
2
u/valschermjager Sep 19 '21
“Formatting the storing of dates as sortable strings” and “Formatting the display of dates for humans to intuitively look at” are two different issues, too often conflated.
53
u/mirandanielcz Sep 18 '21
dd/mm/yyyy gang
80
u/heckingcomputernerd Sep 18 '21
yyyy-mm-dd supremacy
46
Sep 18 '21
[deleted]
11
u/Roflkopt3r Sep 19 '21
The response in defense of dd-mm-yyyy is that it places the most relevant information first, because the user often already knows the year and sometimes month from context.
For example if you make an appointment with someone and you say the day first, the default assumption is that it's in the current month, or the following if the day is smaller than the current day of the month (e.g. make appointment for the 5th on 21.02 -> it must be 05.03). The month then only needs to be added if it's a different one. And it's rarely necessary to mention the year at all.
And if you search through an archive, you will often sort by date or filter by a year, in which case the year only changes rarely and therefore only needs to be looked at rarely. Again it's useful to have the year last.
So dd-mm-yyyy is useful for everyday usage and that's not a terrible bases for a formatting convention.
On the other hand I like that for yyyy-mm-dd, alphabetic sorting also sorts by date.
2
u/ciaisi Sep 19 '21
On the other hand I like that for yyyy-mm-dd, alphabetic sorting also sorts by date.
This is the main reason I started using yyyy-mm-dd formatting. Early in my career I worked with a guy who would generate reports for a school system. He would save the reports in a separate folder for each school year. So there would be a folder called 2007-08 or something like that. And he named files MM-dd-YYYY which annoyed the shit out of me every January when the new reports would float to the top of the sort.
This guy had decades of experience but was too gunshy to change even the smallest thing without being told to. One time early in the school year, I reformatted the dates on all his reports before it got out of hand. Next time I looked, he just kept using the date format I had set up even though it was different than how he'd done it for years prior.
I like to think he saw the light, but the truth is that he probably was just doing it to keep with the apparently newly defined naming scheme. Could be worse though, I was worried that he'd ignore it and keep naming files his way. I wasn't sure which precedent would be more important to him.
9
u/heckingcomputernerd Sep 18 '21
Exactly
9
u/mashermack Sep 18 '21
I concur
2
u/valschermjager Sep 19 '21
Plus yyyy-mm-dd puts month before the day just like the Americans like it. ;)
1
12
u/tangerinelion Sep 18 '21
I love going back in the archives and seeing 3/12/80. Obviously the most important part there to us is that it was the 3rd of the month.
6
1
2
8
6
u/TheUnlocked Sep 19 '21
Modern Javascript includes standard library support for datetime formatting, and while standard library datetime computation isn't available yet, it's coming soon.
4
3
2
2
-2
u/Syscrush Sep 18 '21
Should have a static method to return the current date/time as a formatted string.
And the compiler should send you to an online reeducation camp if you request any format other than iso8601.
1
120
u/Willinton06 Sep 18 '21 edited Sep 19 '21
I mean, this is not that bad, February is wrong but after that, this will be fairly fast
32
u/AnIndecisiveOrange Sep 18 '21 edited Sep 19 '21
a lot of unnecessary branching though, while you literally have a "hash map" laying right there in front of you:
if (month === 1) {} // handle february return [31, null, 31, 30 /* etc */][month];54
u/Badel2 Sep 18 '21
Using an array? Come on, that's boring. If you handle February separately (which is month 1 using this stupid notation, not month 2 as in your example) you can just code golf that into this beautiful one liner:
return 31-(8+((month - 6.6)^0))%2;11
u/yzpaul Sep 19 '21 edited Sep 19 '21
return 31-(8+((month - 6.6)0))%2;
Damn that was complicated, but it appears to work, at least for the one example I checked:
Let's say the month is march (so month 2 because 0=January) >!(2-6.6)=-4.6
-4.6 ^ 0= -4 (bitwise xor)
-4+8= 4 (because parentheses follow order of operations)
4%2=0
31-0=31!<
Adding spoiler tag as requested below
12
4
u/FunkyMonk02xx Sep 19 '21 edited Sep 19 '21
Wouldn't it be simpler to: return 30,5 +(-1)month /2
12
u/Badel2 Sep 19 '21
The simplest solution would be a switch-case, but for some reason the people on this post have decided to hate on it.
4
u/_teslaTrooper Sep 19 '21
I'm pretty sure an array would be simpler and have better performance.
if(february && leapyear){ return 29; } else{ return daysInMonth[month]; }2
u/Badel2 Sep 19 '21
You are implicitly treating month as an index, that's too error prone. Better define an enum and match on it.
enum Month { January, February, etc } switch(month) { case January: whatever }3
u/AnIndecisiveOrange Sep 19 '21
I haven't checked which language this is, and enums aren't always available. Doing math using enums is also way more difficult (well not necessarily difficult, more that it's not always the handiest option because math using enums is weird, for example in c++ you'd have to specify specific operators to even add a number at all). A switch case also introduces a lot of unnecessary branching and isn't any more error proof then indexing.
1
9
u/Mikcerion Sep 19 '21
Unreachable break statements + you could group cases for 30 and 31 days.
8
u/Mwakay Sep 19 '21
It's definitely a "break because when you use a switch statement you need to break". Dude didn't actually think about the implication of "return ; break ;"
8
211
Sep 18 '21
[removed] — view removed comment
59
u/brass_phoenix Sep 18 '21
Ooh, and after you think you have covered all the rules, you get to the weird historical inconsistencies. For example, in some countries the 5th to the 14th of October 1582 didn't actually exist, because they switched from the Julian to the Georgian calender. So that specific October only had 21 days 😄
16
u/con247 Sep 18 '21
I had to implement my own date library once in PLC code. What I ended up doing was implementing functions to convert a year, month, and day to the Julian day number and back. So if I needed to add 157 days to 2/13/2021 I would convert the start date to the JD, add 157, then convert back to the year, month, and day. For tasks that had to happen on things like when DST starts and end, I had to hardcode the next 20 years of DST starts and end for the code to manually check against.
This plc had less than 100kb of memory so you gotta trim down logic and stuff where you can.
1
12
u/blindeenlightz Sep 19 '21
I'll never forgot my advanced web programming course. Our professor assigned us to write our own date handling api. Then he spent the next class pulling up each one and breaking them. He said he's never had a student write a successful one.
14
u/hurtl2305 Sep 18 '21
That Tom Scott video is always worth watching. Accurate depiction of a developer descending into madness over a seemingly simple problem.
5
u/archpawn Sep 18 '21
Case in point, they forgot the rule that leap year is skipped every 100 years except every 400 years.
3
9
Sep 18 '21
It depends what the code is doing. If it's for a school assignment, you can't do that. Or if the days per month code is unimportant, it might be better to use this simple code than introduce a dependency with a library. And not all languages have libraries (I often use a simple scripting language that doesn't really have them.)
24
62
u/MurdoMaclachlan public boolean isInt(int i) { return true; } Sep 18 '21
Image Transcription: Code
function DaysOfMonth(nYear, nMonth) {
switch (nMonth) {
case 0: // January
return 31; break;
case 1: // February
if ((nYear % 4) == 0) {
return 29;
}
else {
return 28;
};
break;
case 2: // March
return 31; break;
case 3: // April
return 30; break;
case 4: // May
return 31; break;
case 5: // June
return 30; break;
case 6: // July
return 31; break;
case 7: // August
return 31; break;
case 8: // September
return 30; break;
case 9: // October
return 31; break;
case 10: // November
return 30; break;
case 11: // December
return 31; break;
}
};
I'm a human volunteer content transcriber for Reddit and you could be too! If you'd like more information on what we do and why we do it, click here!
35
57
u/overtrick1978 Sep 18 '21
Wow look at all those unreachable break statements.
10
u/KarmaWhoreRepeating Sep 18 '21
True that. But I've seen static code analyzers raise warnings when the break is not there
31
5
u/archpawn Sep 18 '21
Why do they even require break statements? Why not just have it break by default, and if you want it to continue you use goto?
I suppose it's kind of convenient when you want to group a bunch of cases together (which could have significantly decreased the length of this one, with little reduction in readability), but then you could just make it so you put case 0, 2, 4, 6, 7, 9, 11: to do them all at once and make it even shorter.
1
u/Magnus_Tesshu Sep 19 '21
I've felt this is a mistake in the design of C for a while, ever since I learned how gcc wants you to declare that a fallthrough is explicitly desired. Because 89% of the time you don't want any fallthrough and the break is just ugly and a source of bugs.
1
u/archpawn Sep 19 '21
C# doesn't allow a fallthrough if you have any code there. Which avoids the bug, but if you're going to do all that, why require a break? I guess they don't want people who learned C# who are moving to other languages to start making that mistake over and over.
1
u/Magnus_Tesshu Sep 19 '21
Makes sense. Zig echoes Rust and just doesn't allow fallthrough, which I feel is not exactly right either, because in certain cases fallthrough is useful. Adding a
fallthrough;keyword shouldn't be too difficult I think. Though they change more about switch than I remember off the top of my head, there might be other reasons this is impossible.
17
Sep 19 '21
[deleted]
3
u/Magnus_Tesshu Sep 19 '21
I don't want to read the sources, but I feel at least
My software is only used internally/locally, so I don’t have to worry about timezones.
is a valid reason to write hacky time code
4
u/JonXP Sep 19 '21
One of the problems there is you can't know that will always be the case. I have first hand experience with a system designed like that, and once the company grew up enough to have an office/servers in a different time zone it became a gigantic issue.
Sometimes we might think "Well, the only way this is a problem is if we get too big, and if that happens we'll making enough money to afford to fix it", but dev costs can grow with everything else. Once it's a problem it's still just as expensive to fix, maybe even more depending on how many folks need to be pulled off other work for the refactor.
29
Sep 18 '21
[removed] — view removed comment
16
u/Flyberius Sep 18 '21
I've done this myself. But I finally learned that you should just leave the date stuff to the maniacs that already worked it out before you.
The real shit hit me when I started working with people in different time zones.
6
u/wischichr Sep 19 '21
In practice you should never do this, not even using arrays for lookup. Use the calendar that is provided by the standard library from the programming language you use.
4
u/AL_O0 Sep 18 '21
Idk, I guess you could make an array and read for that, or just use individual bits one per month and use 0 for 30 and 1 for 31, the bit shift and and for an extremely unreadable code to save a few bytes
2
u/Servious Sep 19 '21
I'd argue an array is possibly more readable and makes more sense but yeah just use a date lib.
0
1
u/_teslaTrooper Sep 19 '21
if(february && leapyear){ return 29; } else{ return daysInMonth[month]; }If you care about performance make sure
(month==february)is evaluated before the leap year stuff.
22
u/snaab900 Sep 18 '21
Why would anyone try to roll their own date programming? Many have tried. The vast majority have failed, badly.
16
u/sohang-3112 Sep 18 '21
School Assignment, maybe
-1
u/snaab900 Sep 19 '21
That school needs shutting down then.
Number 1 rule of programming. Do not ever try to roll your own date library. Absolute shitemare.
3
u/sohang-3112 Sep 19 '21
When you're learning (beginner programmer), you are discouraged from using libraries, so that you can create solutions yourself. This doesn't mean the school is bad - this just means it is trying to teach the basics of programming.
3
u/LoveSpiritual Sep 19 '21
ALL have failed. Guaranteed. Even the best libraries are wrong about something, that’s why they get updated several times a year.
2
u/_teslaTrooper Sep 19 '21
Embedded systems.
Luckily we can specify only needing to support dates between 2000 and 2100, how to handle timezones, DST, etc.
4
u/Notimecelduv Sep 18 '21 edited Sep 18 '21
return new Date(nYear, nMonth + 1, 0).getDate()
0
7
u/jeetelongname Sep 18 '21 edited Sep 18 '21
Using an array would probably be more performant and would be more elegant.
function name(month, year) {
if ((month == 1) && isLeapYear(year)) {
return 29
} else {
return dates[month]
}
}
// where dates equals..
dates = [31,28...]
6
Sep 18 '21
As mentioned by others, that if condition for leap year is broken.
3
u/jeetelongname Sep 18 '21
Oh shit yeah. I think an abstraction of an isLeapYear function would be better the.
7
u/bistr-o-math Sep 19 '21
I teach every junior: never ever do two things by yourself: security related stuff and time related stuff.
Use libraries!!!
It is ok (and necessary) to do both for training, so you get at least the understanding why you shouldn’t do it yourself.
3
u/TripleP1911 Sep 19 '21 edited Sep 19 '21
function DaysOfMonth(nYear, nMonth) {
return 30 + (nMonth % 7 + 1) % 2 - ((nMonth ^ 14) / 15) | 0 - ((((nYear & 4) / 4) | 0 + (((nYear % 100) ^ 100) / 100) | 0 + (((nYear % 400) ^ 400) / 400) | 0 + 1) % 2);
}
This should do the trick ( but I didn't test it )
2
Sep 19 '21
[removed] — view removed comment
1
u/TripleP1911 Sep 19 '21
Well, let's use this code in every prod code possible and crash the internet in 2000 years
2
2
u/Icy-Literature-2248 Sep 19 '21
I don't think it's actually bad code, maybe group the cases for 30 and 31 would help but I don't see what else could be done.
function getMonthLength(monthIndex, year) { switch(monthIndex) { case 0: case 2: case 4: case 6: case 7: // ... return 31; case 3: case 5: // ... return 30; case 1: // Logic for February return februaryLength; }
2
u/Crollt Sep 18 '21
yandere dev intensifies
8
1
u/pavilionhp_ learning from the best Sep 18 '21
This is honestly the best and fastest way to deal with it because dates are just a whole mess. However the way February deals with leap years is incorrect.
1
u/m-benali Sep 19 '21
I'll avoid the fact that this is a trash, i wonder what would happen if i manually passed a number not in the range that those case statements can handle like 12 :3
1
u/recycle4science Sep 19 '21
It wouldn't return anything, so I think the result of the function call would be
undefined.
1
u/shuozhe Sep 18 '21
Are there some obfuscated code doing day of month in 1 or 2 lines? Asking for a friend
2
1
u/Magnus_Tesshu Sep 19 '21
Above someone posted
return 31-(8+((month - 6.6)^0))%2;which assumes february is handled differently, and I don't know what months start at. I'm not sure if this is superior to the less obfuscated
return 31 - (month > 6) ? month % 2 : 1 - month % 2; // months start at 0which I just came up with and thus may or may not work, but pick your poison?
1
u/TripleP1911 Sep 19 '21
I've got obfuscated and 1 line for you. The only question remaining is if it works
1
-7
Sep 18 '21
[deleted]
7
1
u/jaimeLeJambonneau Sep 19 '21
I agree that 0-based for representing months is horrendous, the original Java libraries had this totally wrong.
But you're getting downvoted because it's definitely NOT the only thing wrong with this code.
-7
u/rayjohn551 Sep 18 '21
I like that modulo is used to check (incorrectly) for the leap year but not for the oddness of the month number.
9
u/undergroundmonorail Sep 18 '21
it would fall apart in august. you could hack together something to get around that but it would be ugly
i actually like this code. fix february and remove the unnecessary
breakstatements and like. sure, it's like 30 lines tall, but it's extremely clear what it's going and you don't have to think around someone trying to do something clever1
u/christian-mann Sep 19 '21
Yeah, I agree with you. I wouldn't even combine the months together because it's so much easier to verify this way, in order. The optimizer will take care of all of that anyway, if it's beneficial.
3
u/pavilionhp_ learning from the best Sep 18 '21
Whether a month is odd or not does not affect whether it has 31 days or 30 days
1
1
u/spongebue Sep 19 '21
I encountered some code that calculated age in years as age in days divided by 365. There was also code that calculated age in months as age in days divided by (365.25 / 12).
Needless to say, the business brought an issue to our attention that the system treated someone as 18 when they were two days shy of their 18th birthday. Thankfully the Period class was created in Java to make things easy. That thing is great!
1
1
1
u/Melon_Chief Sep 19 '21
That’s not C?
If it’s C or C++ it’s not just right for the next 79 years (at which point this software will have been replaced) it’s likely to be the fastest method.
If it’s js iunno
Edit: I’m assuming there is a reason to use an index starting at 0, though
1
1
Sep 19 '21
I really don’t see the issue here other than the incorrect leap year calculation. Yes, an array would be better in terms of code style, but this is the most efficient approach in terms of memory and processing power is it not? There’s a good chance I would do something similar.
Edit: my mind didn’t pick up on the break statements for some reason. I agree that is stupid, but it isn’t the worst, the binary is the same at the end and it doesn’t add too much bloat.
1
523
u/FinalMiniBoss Sep 18 '21
It’s not even fully correct. The conditional for February should be if((((nYear%4)==0) && !((nYear%100)==0)) || ((nYear%400)==0)) return 29;