You may also be interesting to seeing the shenanigans from 2020 and 2016.
Last updated 2024-03-01 6:18 PM PST
Highest Impact
Medium Impact
2004-02-29 is a valid date, but 2002-02-29 is not.Low Impact
phx.gen.cert task attempted to create a certificate with an invalid expiration date of 2025-02-29. A fix for the issue has been created, and should be included in the next release to prevent the problem from occurring again next leap year.4.4", it then it reports that is also +4.4" above the 30 day average of 0". (Note: I was able to verify this independently.)2024-02-29 is a valid date or not. At least one user of the OpenAI API encounter failures in their own application due to this issue.04.03.00.Unknown Impact
datetime_to_time function, which results in March 1st, 2024 incorrectly being coerced to February 29th, 2024. According to its maintainer in the comments below, the problem has been fixed in the latest commit, and will be included in the next monthly release dev-2024-03.Unconfirmed / Coincidently Timed
1970-01-01 (the date of the Unix epoch) in the file name where it should have been 2024-02-29. However, the contents of the invoice appeared to be correct.Maybe Not a Bug
Got some that aren't in my list? Please let me know and I'll add them! See my About the Author page for contact info, or just comment below. Thanks!
]]>Last updated 2020-05-25 11:32 PM PDT
Items in this section have been verified, and have not yet been resolved.
exa, a replacement for ls, shows file timestamps from Feb 29th incorrectly as March 1st. The issue was also reported last leap year, but has not yet been repaired.DateTime::createFromFormat with day of year placed before the year. Reported in 2012, and never fixed. Workaround: Put the year first. (This was in my list from last leap year also.)Items in this section have been verified, and have a fix ready - pending release.
Items in this section had an impact on or near February 29th, were verified as actual bugs, and are now reported as resolved.
Items in this section had an impact on February 29th, but were either resolved through manual workarounds, or resolved themselves on March 1st without any specific fix or resolution reported. One assumes that the responsible party will take appropriate action before the next leap day in 2024, or has already taken such action, but to the best of my knowledge no confirmation of that has yet been provided.
Items in this section have been verified to have occurred near the leap day, but may or may not have been caused by a leap year bug.
Items in this section have been verified to have occurred near the leap day, but were confirmed to not have been caused by a leap year bug.
The stock trading platform Robinhood experienced multiple system-wide outages on March 2nd and March 3rd, that many people attributed to the leap year. Robinhood disagreed, stating:
The outage was not caused by a failure to code for the leap year. We had instability in a part of our infrastructure that allows our systems to communicate with each other.
Reportings: 1, 2, 3, 4, 5 (and many others)
A Robinhood engineer also later confirmed that it was not leap year related.
The certificate authority Let's Encrypt had an issue related to CAA Rechecking on Feb 29th. The bug was not related to leap year.
These items surfaced during my search or were brought to my attention by others, however I have not been able to confirm their validity. They may possibly not have happened at all.
You might also be interested in these other articles I've authored on the subject of leap year bugs:
Please let me know (in comments below, or send me a DM on Twitter) if you have any corrections or additions. Thanks.
]]>I've gathered quite a bit of knowledge in this area since then. Hunting down leap year bugs has actually been part of
]]>I've gathered quite a bit of knowledge in this area since then. Hunting down leap year bugs has actually been part of my full-time job for the last few months, believe it or not. When you work at a company like Microsoft, the sheer quantity of code written over the course of four years makes this a daunting task, but also a necessity.
Before we dive in to leap year, let's consider the life cycle of most bugs in software. They probably go something like this:
Sure, that's glossing over many areas, but it's roughly what happens. The interesting part is that usually the entire life cycle is on the order of days, weeks, or maybe months at most. Also normal bugs tend to happen one at a time, or a few with each release.
Leap year bugs are not like this. They have a very different life cycle.
It's interesting to me that despite so many documented cases of leap year bugs, that this is not better understood by our industry. In an effort to fix that, I've started tracking types of leap year bugs in a Stack Overflow posting. If you don't know what leap year bugs look like, or if you have any to contribute, please take a look there. I've seeded it with two common cases, and I'll add more over time.
Let me know in comments here what you think! I can always blog more too. :)
]]>How do I get the epoch time?
Or maybe:
I have an epoch time and I want to get the next day's epoch time.
Or even better:
I changed]]>
How do I get the epoch time?
Or maybe:
I have an epoch time and I want to get the next day's epoch time.
Or even better:
I changed my epoch time to a different time zone and...
This is rubbish. Stop. Please, just stop and look at the words you are using. Maybe you just have some large integer number and someone told you it was an "epoch time" so you think "epoch" is some name assigned to this sort of thing. It's not. Epoch is an English word.
According to Merriam-Webster:
epoch
noun | ep·och \ˈe-pək, ˈe-ˌpäk, US also and British usually ˈē-ˌpäk\1a: an event or a time marked by an event that begins a new period or development
1b: a memorable event or date
2a: an extended period of time usually characterized by a distinctive development or by a memorable series of events
2b: a division of geologic time less than a period and greater than an age
3: an instant of time or a date selected as a point of reference (as in astronomy)
Note in particular that the word is a noun. When one says "epoch time", they are using epoch as if it were an adjective. It is not.
Of the above definitions, the third is the only one that applies in computing - in the same way that it does in astronomy.
An epoch is a reference point. It is the timestamp with the value 0. It makes no sense to take a timestamp like 1507163237 and call it an epoch!
Well, you're getting a little closer to the truth now. But please understand, while 1970-01-01T00:00:00Z is indeed the "Unix epoch", it is called this because that is the time we assign to 0 for a Unix timestamp. So when you have a value like 1507163237, that is a Unix timestamp, not an epoch.
One only needs to point at the Wikipedia article on Notable epoch dates in computing. Yes, there are multiple of them. Depending on what you're doing, 0 might not be the Unix epoch, but some other epoch entirely. Also note that that while the Unix epoch is always describing time on an absolute, universal time scale, some of the other epochs are not necessarily UTC based.
As an example, consider that "ticks" in a .NET DateTime object are based on a 0001-01-01T00:00:00.0000000 epoch. One has to consider both "ticks" and "kind" to construct a DateTime, and "kind" is sometimes unspecified, meaning it cannot necessarily be mapped back to a point in UTC time. O_o
Probably not. I think people know what you mean when you say "epoch time". I just think it's a bit silly.
]]>I also recorded the presentation, and you can watch it on YouTube here (or below).
If you attended my talk - Thanks!
]]>I also recorded the presentation, and you can watch it on YouTube here (or below).
If you attended my talk - Thanks! Please feel free to send any constructive feedback, positive or negative. I am always looking to improve my speaking and teaching skills.
Cheers!
On Microsoft Windows desktop or server operating systems, you may find that
]]>On Microsoft Windows desktop or server operating systems, you may find that the time will automatically change on the morning of Friday, July 8th. This is because Microsoft issued KB3162835 in June which reflected the Egyptian government's previous decision to enact DST from July 8th through the end of October. If you are applying automatic Windows updates, or getting the monthly builds of Windows 10, then you likely have this on your system already. (An easy way to tell is to check if any of the newly added zones mentioned in the KB are present in the list of time zones on your system settings or control panel.)
Unfortunately, there simply isn't enough time between the date that the government changed their mind and the previous effective date for Microsoft to create, test, and distribute another update to retract this. Microsoft is working on an update to release in the near future, but the availability date is uncertain at this time. Meanwhile, many computers will reflect the time in Egypt inaccurately.
Microsoft's official guidance on this matter recommends two possible options:
tzutil /s "Egypt Standard Time_dstoff"
(UTC+02:00) Harare, Pretoria, or (UTC+02:00) Tripoli. Neither of these use daylight saving time in 2016. This is a good option for those on Windows Phone 10 devices, which do not have an option for disabling DST. Note that earlier versions of Windows Phone did not receive the June DST update, so they do not need to be changed at all. These are both great options, and are the only official recommendations from Microsoft. However, they do not cover all possible uses of time zone information. Other common uses include:
TimeZoneInfo class to provide accurate time for multiple time zones within a custom application.For these scenarios, and many others, it makes more sense to correct the underlying Windows Registry data for the Egyptian time zone. I have created a .REG file for this purpose, which you can download here. Running this file on your system will correct the time zone information for Egypt Standard Time, removing the DST information for 2016, and canceling it for all future years as well. DST information for 2015 and prior is left intact. It is designed to be ran on Windows Vista and newer operating systems only.
Please note that this file is is an UNOFFICIAL and UNSUPPORTED patch, provided "AS-IS" by myself, Matt Johnson, independently of any activities of Microsoft. While I do work for Microsoft, I do not work in the Windows group, and this is not a Microsoft product or supported solution. Examine the registry file for yourself before making the decision on whether to apply it to your computers. While I am confident that it will cancel DST for 2016 on your computers, I take no responsibility for any effects or side effects it may have.
If you're running a desktop operating system other than Windows, or any platform that uses the IANA time zone database, you can probably just update your tzdata distribution to 2016f, announced here. However, for phones running iOS and Android, unfortunately you may have to wait for a system update to get the Egyptian time zone fixed. Consider using the time zone of South Africa or Libya in the meantime.
If you have any questions about this, please ask in comments below. I hope this helps a few people out there work around this issue until an official update can be provided.
The current time in Egypt is shown below. If the time on your clock is showing an hour ahead, then you need to disable DST, choose a different time zone, or update your system.
]]>Note: Some of the articles linked below may be in Arabic. If, like me, you do not read Arabic, consider using the Google Translate Plugin within Chrome. It works much better than using the Google Translate site directly, and better than other translator tools I have tried.
Originally, the Egyptian Cabinet announced (on April 29th, 2016) that daylight saving time was to take effect starting July 7th at 24:00 (which is the same as July 8th at 00:00), and that it was to go through "the end of October". This was widely interpreted as meaning it would end on Friday October 28th at 00:00 - as in the past all DST changes in Egypt have occurred on Fridays. This was agreed upon by all key parties in the time zone community, including IANA, Microsoft, and third party sites.
Both IANA and Microsoft released updates accordingly. IANA with TZDB 2016e, and Microsoft with the June 2016 DST/TZ Update. Between the two of these, it is likely that most computers and smartphones will advance their clocks by an hour on the morning of July 8th. Well, at least those that have the updates installed will anyway.
However, two months later on June 27th, with less than two weeks before the previously announced effective date, the Egyptian Parliament voted overwhelmingly to abolish daylight saving time completely.
This has been followed up with many other news reports, including:
And of course, the kicker is that even with all of these votes and announcements by the warring parties, there is not a single stitch of official published documentation to be found. Not a single law passed, decree proclaimed, or even any acknowledgement by the State Information Service. There are lots of other things being published - but somehow something as vital as a time change isn't worthy of documentation.
I previously wrote about the issues with short-notice time zone changes, and described what has happened in other countries in the past. I also gave some advice to countries that are making time zone or daylight saving time changes - advice that Egypt certainly has not heard. I'll also quote a member of the IANA TZ community who said it quite well:
If only it were made more clear that there very likely exists a point in time beyond which the costs incurred from having to deal with any particular observance or non-observance of DST are dwarfed by the costs incurred from uncertainty and duplication of effort in the lead-up to and in the wake of last-minute policy changes.- Tim Parenti
July 1, 2016
At this point, all any of us can really do is monitor the situation and hope that things work themselves out. The best case would be for the start of DST to occur as it was originally announced and implemented in technology - on midnight between July 7th and July 8th.
Either cancelling DST for this year, or moving the start date up, will mean that the clocks on computers and smartphones will not agree. The likelihood of economic impact would increase significantly. Some people will miss important meetings. Some people will miss their flights. It will likely affect stock trading, traffic patterns, and other aspects of society that are time sensitive. Some aspects of this are inevitable no matter what happens, as just like financial markets, uncertainty is never a good thing.
Whatever happens - next time around, please Egypt, announce the change far in advance, in an official published decree or law, and do not deviate from it at the last minute, or even entertain the idea of deviating from it. The turmoil that uncertainty creates is more costly than any potential energy savings.
July 4th, 2016
On July 4th, just four days before DST would go into effect, the Egyptian Cabinet announced that they would accept the Parliament's decision to abolish DST. While it's good to finally have consensus, the timing is pretty awful. There's just not enough time to create, test, distribute, and install updates for computers and smart phones. Thus it's quite likely that on July 8th, there will be considerable confusion about what time it is.
As a general recommendation, users in Egypt should temporarily disable daylight saving time on their computers and devices, if their devices support doing so. Otherwise, they can choose a nearby UTC+2 time zone that does not use daylight saving time this year. Libya or South Africa are reasonable choices. Eventually, software vendors will distribute the appropriate updates and users can switch back to Egypt time after installing them.
July 6th, 2016
July 6th, 2016
July 7th, 2016
As I'm writing this from the USA, it's July 7th still, but in Egypt it's already in the early hours of July 8th. After the clocks struck midnight, several reports began coming in:
Also, there were several reports about comments by a member of the TZ community. Some reports were more accurate than others. The comment in question was the well-established adage:
"Poor planning on your part does not constitute an emergency on mine!"
(widely attributed to Bob Carter)
In this case, the TZ member who aptly used this quote to describe the Egypt DST situation was absolutely correct, and I stand with him in this regard. However the comment was misinterpreted by several Egyptian outlets as a refusal to help. Other news reports were a bit more accurate. This one is probably the best I could find, and includes additional details. Indeed, a fix was already in progress, and was released by IANA the very next day.
July 8th, 2016
As expected, there are even more reports of time confusion today:
August 18th 2016
Microsoft has finally released a fix for Windows, in KB3177723. Windows 10 users can simply install the latest OS build to receive the update.
Additional updates will follow as this event unfolds.
]]>No, that's not the punchline to a joke. It's actually quite a serious problem. The biggest issue with time zones is not that they exist, nor
]]>No, that's not the punchline to a joke. It's actually quite a serious problem. The biggest issue with time zones is not that they exist, nor that they have daylight saving time. But rather, in that they often change in a haphazard manner. Allow me to explain.
First, understand that from a global perspective, one might think that the time zones of the world should be managed by some relatively neutral international body, such as the ITU division of the United Nations, or perhaps the IAU. However, each of the world's time zones are actually controlled from a local perspective. Each individual nation has a sovereign right to decide the local time for the lands within their jurisdiction. This includes both the offset from Universal Time, and the rules that govern daylight saving time, if they choose to use it.
This unto itself is not a problem, and absolutely I agree that countries should be able to do whatever they want with the clocks within their borders. However, time and time again, we run into the same problem, which is simply that they are changed without enough notice. All of the countries mentioned earlier have done this recently, along with many others.
It's crucial that when governments make changes to their time zones or daylight saving time rules, that they provide ample lead time for technology to catch up. One has to consider the real work that people have to do to validate the change, create a data update, test the changes, and to publish and distribute the update. Then you have to consider that individuals don't always update their systems instantly. It's very common for a time zone update to be available for weeks or months before it is actually installed by the end user.
Let's look at Turkey as an example. In 2015, the government decided that it would be a good idea to delay the end of daylight saving time by two weeks to allow for more daylight hours at the polls during their election season. They moved the end of DST date from October 25th to November 8th.
So what was the result? Well, to quote the BBC:
Confused Turks are asking "what's the time?" after automatic clocks defied a government decision to defer a seasonal hour's change in the time.
Millions of Turks woke up to a confusing morning on Sunday ... as smartphones, tablets, and computers had automatically updated in keeping with other countries in the Eastern European Time zone, even though Turkey delay setting clocks back an hour for the next two weeks.
You can imagine that this probably had exactly the opposite effect on voting than what was envisioned. However, you think they would have known better, since almost the exact same thing happened the previous year! As reported by the Independent Balkan News Agency in 2014:
An unbelievable confusion to 52.9 million Turkish voters was caused by the decision of the turkish government to postpone for a day the time shift applied all around the world, where the indicators are turned one hour forward. The reason for postponing the application of summer time according to the Erdogan government, was to facilitate the smooth conducting of the elections, but nobody predicted the "new technology" factor. All smart phones of the Turkish citizens changed the time automatically, resulting in thousands of voters going to the polls earlier having to wait for an hour to vote.
Similar problems were also caused to computers that had not downloaded a new version of the software. Problems also occurred in the luggage delivery system at Istanbul’s airport as the system automatically changed the time, ignoring the government’s plans and as a result the luggage were delivered to the passengers with great delay. There were also problems with many flights as passengers were confusing their departure time.
Not only did Turkey not learn from their own mistakes, but other countries around the world also have failed to learn from the experience and continue to have this problem. Remember the list I rattled off earlier? Let's take a closer look:
While all of the above changes come with a certain degree of surprise, there are other some parts of the world that simply don't make any advanced schedule at all for their daylight saving time rules.
Fiji is one such time zone. It has had DST every year since 2009. However, each year, the government issues an announcement stating what date it will begin and end. It's slightly different each year, and it's unclear exactly when the government will reach their decisions, or what to do in the absence of an announcement. It would be much simpler if they would just decide on a regular schedule, and only make announcements if there are deviations from that schedule.
Another such place is Morocco, where the schedule for the first start of DST and last end of DST are adequately defined, but every year since 2012 there has been a "DST suspension period", such that DST ends before the start of Ramadan, and is restored sometime after. Not only does this mean that the clocks need to be changed four times in a single calendar year, but it also means that nobody is fully certain of when the middle two transitions will occur until the government makes an announcement. Part of the reason for this is that the dates for Ramadan are based on the observed sighting of the new moon. However, my personal opinion is that they should still fix the DST transitions to some schedule, even if it starts before Ramadan and ends sometime after. The unpredictability of the dates makes it just too difficult to know what time it is in Morocco unless you are are actually there. (By the way, Egypt used to do this as well, but only in 2010 and 2014.)
First, I must emphasize that these are my personal recommendations. I am not speaking on behalf of my government, my employer, nor the TZ community. These recommendations are based on years of experience working with time zone data in computing, and the observation of real events.
If you're going to make changes to your time zone(s), whether they are for the standard time offset from UTC, or to the enactment or abolishment of daylight saving time, or to the dates and times that daylight saving time occurs then please do all of the following:
Following these guidelines will ensure that your change is observed by technology, including computers, cell phones, and other devices.
If you're looking for information of how to avoid leap year bugs, or examples of disastrous leap year bugs from
]]>If you're looking for information of how to avoid leap year bugs, or examples of disastrous leap year bugs from previous years, please read my article on the Microsoft Azure blog.
Please let me know if you have any corrections or additions. Thanks.
Last updated 2019-04-03
Items in this section had an impact on February 29th, but resolved themselves on March 1st without any specific fix or resolution reported. One assumes that the vendor will take appropriate action before the 2020 leap day, or has already taken such action, but to the best of my knowledge no confirmation has yet been provided.
Items in this section had an impact on February 29th, were verified as bugs, and are now resolved.
/favicon.ico. Fixed in versions 1.7.0 and 2.0.0.Items in this section are also verified and resolved, but the vendor did not supply any supporting details as to what problems they actually had.
DateTime::createFromFormat with day of year placed before the year. Reported in 2012, and never fixed. Workaround: Put the year first.These items surfaced during my search or were brought to my attention by others, however I have not been able to confirm their validity. They may or may not have been caused by the leap day, or possibly not have happened at all.
time.strptime function) Not really a "bug", but just a commonly misused API. Evaluating future change as an enhancement. Looking to avoid leap year bugs next time around? Check out my original post about leap year bugs. And don't forget - December 31st 2016 is another important date!
"Meh," you say. "My code is just fine. We have unit tests."
"Oh really", I say. "Do your tests properly mock the clock? Do they test edge cases including February 29th and December 31st? Have you tested any low-level C++ code you might have as well as the rest of your system? Do you even know what a leap year bug looks like?" Most often, blank stares.
There's a lot to cover here, so let's start with the most important things first.
In C / C++ code that uses the Win32 API, the SYSTEMTIME structure is a common representation of civil time. It has distinct fields for each part of a date, separating the year, month, day values (and others). It is very common to see the following code:
SYSTEMTIME st; // declare a SYSTEMTIME variable
GetSystemTime(&st); // set it to the current date and time
st.wYear++; // increment it by one year
This code will succeed without error. However, the risk is that if the code is called on February 29th, the resulting value will still be on February 29th, but in a non-leap year. For example, 2016-02-29 + 1 year = 2017-02-29, which does not exist!
This value might be passed around quite a bit before it ultimately ends up as a parameter to another function, such as SystemTimeToFileTime, where it will cause the function to fail with a return value of zero. Unfortunately, it is extremely common to find code that uses this method without checking the return value. This can lead to unpredictable results, such as leaving a FILETIME value in its uninitialized state.
SystemTimeToFileTime.SYSTEMTIME by checking the validity of the result and adjusting when necessary:SYSTEMTIME st; // declare a SYSTEMTIME variable
GetSystemTime(&st); // set it to the current date and time
st.wYear++; // increment it by one year
// check to see if it's a leap year
bool leap = st.wYear % 4 == 0 && (st.wYear % 100 != 0 || st.wYear % 400 == 0);
// If it's Feb 29th, but it's not a leap year, then move back to Feb 28th
st.wDay = st.wMonth == 2 && st.wDay == 29 && !leap ? 28 : st.wDay;
Note that a similar bug can also occur in standard C++ (non-Windows) code as well. The tm struct is used instead of SYSTEMTIME, which has slightly different behavior. Months are 0-11 instead of 1-12, so Februrary is month 1. Instead of SystemTimeToFileTime, you might call _mkgmtime to produce a time_t structure. The key difference though is that instead of it failing, when passing February 29th in a non-leap year, it will produce a value that represents March 1st. Your application may be expecting February 28th, and if so it will need to adjust.
int items[365];
items[dayOfYear - 1] = x;
The above C code could just as easily be rewritten in C# or another language, or use a string or some other data type instead of an integer. The key point is that we're declaring a fixed-size array to hold data, and assuming that there will be a location in the array for every day of the year. The problem, of course, is that in a leap year, there will not be a place in the array for the 366th day, December 31st.
The effects of this vary considerably by language. In C#, this will cause an IndexOutOfRangeException. In C, unless the bounds checking compiler option is enabled, this will create a buffer overflow, the effects of which could be negligible, or considerable. JavaScript developers have less to worry about in this regard, as a 366th element will be added automatically.
There are other effects of leap year bugs that can affect data anywhere from February 28th of the prior year, to March 1st of the following year. Usually these are in data filtering, where a range query doesn't account for the extra day - either by assuming a year is always 365 days, or assuming February is always 28 days. Consider a SQL statement such as:
SELECT AVG(Total) as AverageOrder, SUM(Total) as GrandTotal
FROM Orders WHERE OrderDate >= @startdate AND OrderDate < @enddate
This query is fine, but consider what happens if @enddate is set to today, and @startdate is set to today minus 365 days. If the range happens to include the February 29th leap day, then it's not covering an entire year. The start date is one day short, and thus the values are incorrect, assuming the intent was indeed to represent one year's worth of data.
When evaluating bugs like this one, ask yourself what the impact of the bug is. In this case, where are these values displayed? For example, if the average order amount is feeding a chart on a dashboard that gets updated every day, it might not be quite as important as when the total sales for the year is listed in a company's financial report such as an SEC filing. Of course, this assessment requires someone familiar with the application and it's usage; there is no one-size-fits-all rule to follow.
It may be tempting to solve this problem with an approach such as this:
TimeSpan oneYear = TimeSpan.FromDays(isLeapYear(endDate.Year) ? 366 : 365);
DateTime startDate = endDate - oneYear;
However, this is approach is flawed. One cannot determine the number of days to add just by evaluating the year alone. Consider that endDate could be 2016-01-01, and though 2016 is a leap year, there's only 365 days to subtract to reach 2015-01-01. Instead, you have to consider whether or not the February 29th leap day is included in the range. This leads to some fairly complex code if you try to do it by hand, especially when you consider covering multiple years instead of just one.
Ultimately, it comes down to the fact that TimeSpan in .NET (and similar types in other languages) is a representation of absolute time, and both "year" and "month" are units of civil time. The absolute amount of time in a year or month is variable depending on which years or months you are describing. (The same can actually be said for a "day" when you consider daylight saving time, though that's getting off-topic for this post.)
The correct solution for .NET is:
DateTime startDate = endDate.AddYears(-1);
The AddYears method correctly implements all of the necessary logic to determine how many days to move forward, or backwards in the case of a negative value.
JavaScript developers really should be using moment.js for this, where it's as simple as:
var m = moment();
m.add(1, 'years');
However, some folks still like to do things the hard way so you'll often see this:
var d = new Date();
d.setFullYear(d.getFullYear() + 1);
The problem here is one I mentioned earlier. If today is February 29th of a leap year, then the resulting value will be March 1st. That may or may not be acceptable to you. Consider that for every other date, the result is in the same month as the original value. Also consider that your application may be expecting an end-of-month date instead of a start-of-month date.
Here is a function you can use to correctly add years in JavaScript without requiring a full library:
function addYears(d, n) {
var m = d.getMonth();
d.setFullYear(d.getFullYear() + n);
if (d.getMonth() !== m)
d.setDate(d.getDate() - 1);
}
// example usage
var d = new Date();
addYears(d, 1);
This implementation adds the years, and then checks to see if the rollover to March occurred or not, and compensates if it did. Again, do not try to implement this by figuring out exactly how many days to add - unless you really know what you're doing.
There are many other things developers get wrong related to the leap year, such as:
IsleapYear(year) branch at the top, which clearly was never tested. I'm often asked about two other approaches:
It would be wonderful if there was just a set of tools you could run against your code that would point out where you had leap-year bugs. Unfortunately, I don't know of any. Simple string-search, or even regex search, can only get you so far.
Truly what is needed for .NET is a comprehensive set of Roslyn Analyzers that can catch common date/time bugs including leap year, time zone, daylight saving time, parsing, and more. Unfortunately, I have not the time to create such analyzers myself. Maybe I'll get to that at some point in the future, but it doesn't exist today.
It would also be nice to have similar tools for C++, JavaScript, and other languages. Though I know of none.
Why not just move the clock forward and see what happens? That might actually work for some systems, but there's a few problems with this idea.
So, in general, I recommend against this approach.
How do you test code that behaves differently on different dates? Mock the clock!
This is a common pattern found in many reliable systems. The key point is that the system clock - you know, the thing that tells you what time it is - should not be used haphazardly. Application logic should never make a direct call to DateTime.Now or DateTime.UtcNow or new Date() or GetSystemTime or whatever the equivalent is in your language to get the current date and time.
Instead, you should treat the clock as a service (in the DDD sense), and like any service, you should be able to mock it.
For example, in .NET, instead of directly calling DateTimeOffset.UtcNow (or similar APIs) from application logic:
IClock with a method GetCurrentTime that returns a DateTimeOffset.SystemClock class that implements from IClock, where GetCurrentTime calls DateTimeOffset.UtcNow.FakeClock class that implements IClock, which accepts a fixed value as a constructor parameter and where GetCurrentTime simply returns the fixed value.IClock interface. Typically this is constructor injected.FakeClock during testing, and wire up a SystemClock at runtime.This may sound like a lot of work, but once you go through the motions you'll see where it has advantages. This is truly the only way to ensure all of your code is tested when the current date and time are dependencies.
I intentionally did not provide code for this here, as the pattern should be the same for many different languages. Also, there's already a really great implementation of this in Noda Time, which comes with IClock and SystemClock in the main assembly, and FakeClock in the NodaTime.Testing assembly. You'd do well to use Noda Time for this, and many other reasons.
Leap year is here. It's not Y2K, or Y2038, but it is something we have to contend with on a regular basis. How much code did you write over the last four years? Are you sure it's all up to par? Take the time now to test and scan through your code. You will probably find a few things you didn't realize were lurking in the shadows.
]]>I'll also be giving a talk on this subject at CodeMash in Ohio, Jan 7th 2016. If you&
]]>I'll also be giving a talk on this subject at CodeMash in Ohio, Jan 7th 2016. If you're going, stop by and say hello!
]]>"Yeah Buddy,"
"Guess what time it is?"
"... I ... Don't ... Know !!!"
"It's time to... uh.. to.. Hey, what the hell time is it anyway?!!
]]>"Yeah Buddy,"
"Guess what time it is?"
"... I ... Don't ... Know !!!"
"It's time to... uh.. to.. Hey, what the hell time is it anyway?!! What's going on!"
"I used to know, or I used to think I knew. I just don't know any more!"
"I don't know either."
MISSION ACCOMPLISHED!
]]>Many thanks to the .NET Developers Association here in Washington for putting on this event. I hope to come back and speak again next year!
If you're interested in time, especially with .NET, I hope you will listen!
Check it out in show #485.
If you're interested in time, especially with .NET, I hope you will listen!
Check it out in show #485.
var d1 = new Date("2015/06/17");
var d2 = new Date("2015-06-17");
How about these?
var d1 = new Date("2015/06/17 00:00:00");
var d2 = new Date("2015-06-17]]>var d1 = new Date("2015/06/17");
var d2 = new Date("2015-06-17");
How about these?
var d1 = new Date("2015/06/17 00:00:00");
var d2 = new Date("2015-06-17 00:00:00");
Or these?
var d1 = new Date("2015/06/17 00:00:00");
var d2 = new Date("2015-06-17T00:00:00");
Still unsure? How about now?
var d1 = new Date("2015/06/17 00:00:00");
var d2 = new Date("2015-06-17T00:00:00Z");
Ah, that's it! In all of the above examples, d2 is parsed as UTC, while d1 is parsed as local time. This occurs because all of the d2 strings are valid under ISO 8601.
There's a problem though. ISO 8601 specifies that time without a Z, and without an offset (such as -08:00) should be treated as local time. In the above examples, all but the last one were without offset - so why were they parsed as UTC?
Well, in the EcmaScript specification (up to and including the current ES5.1), there is part of the spec that states (in section 15.9.1.15)
... The value of an absent time zone offset is "Z".
That explains the current deviation from ISO 8601, and why folks have trouble understanding why they get the "wrong" date when they do something like this (screenshot from Chrome):
So, to make this align with the ISO 8601 spec, this line was changed in the ES6 specification (in section 20.3.1.16). It now says:
... If the time zone offset is absent, the date-time is interpreted as a local time.
That's great for compliance and spec alignment. But it's a serious issue for backward compatibility. Any code that expects the Date constructor to parse a date as UTC will need to be updated.
To maintain compatibility as ES6 is adopted, it's important to not rely on this bit of functionality. Instead, if you to parse as UTC then you should explicitly add the Z.
var d = new Date("2015-06-17Z");
This will parse as UTC both today with ES5, and tomorrow with ES6.
If you need to parse as local time, you could consider using the slashes, like I showed as d1 - but this isn't guaranteed to work in all browsers. (I've been told that it doesn't work in some versions of Safari.)
A better approach, for both local and UTC, is to use Moment.js.
var m1 = moment("2015-06-17"); // local time
var m2 = moment.utc("2015-06-17"); // UTC
Both m1 and m2 are moment objects, so if you need a Date, then call .toDate(). Or if you need a string, then use .format() or .format("MM/DD/YYYY"), or any of the other functions offered by the library.
Regardless of whether you use a library or manually add a Z, you should prepare for this change today so that you won't be bit by this as ES6 starts making its way into browsers.
This matter was also discussed in ECMAScript tc39 issue #87, and then the spec was augmented in PR #138. The net effect is that date-time forms such as "2015-11-04T00:00:00" are indeed interpreted as local time, per the ES6 spec and ISO8601, but the date-only forms such as "2015-11-04" are still interpreted as UTC. The first part is great, but the second part is really confusing and doesn't match ISO8601. In my opinion, all browsers should treat both forms as local. They should only be treated as UTC if they are followed with Z or +00:00.
Currently, all modern browsers except Chrome will treat the date-time form as local, and all modern browsers treat the date-only form as UTC.