Daniel has a bit of a story. The story starts many months ago, on the very first day of the month.
Angular 1.x has something called a filter
as a key concept. This is a delightfully misleading name, as it's more meant to be used as a formatting function, but because it takes any arbitrary input and converts it to any arbitrary output, people did use it to filter, which had all sorts of delightful performance problems in practice.
Well, Daniel found this perfectly sensible formatting filter. It's well documented. It's also wrong.
/**
* Given a timestamp in the format "2018-06-22T14:55:44+00:00", this filter
* returns a date in human-readable format following our style guide.
* Assuming the browser's timezone is EDT, the filter applied to the above string
* would return "Jun 22, 2018 10:55 AM".
*
When applicable, this filter returns "today at" or "yesterday at" as date abbreviations in lowercase.
* These can be capitalized using the "capitalize" filter above directly in an HTML file.
*/
ourApp.filter('ourTimestamp', ['$filter', function($filter) {
return function(timestamp) {
// Guard statement for when timestamp is null, undefined or empty string.
if (!timestamp) {
return '';
}
let TODAY = new Date();
let TODAY_YEAR = TODAY.getFullYear();
let TODAY_MONTH = TODAY.getMonth();
let TODAY_DAY = TODAY.getDate();
let TIMESTAMP_FORMAT = 'MMM d, y h:mm a';
let TIME_FORMAT = 'h:mm a';
let originalTimestampDate = new Date(timestamp);
let year = originalTimestampDate.getFullYear();
let month = originalTimestampDate.getMonth();
let day = originalTimestampDate.getDate();
let dateAbbreviation = null;
if (year === TODAY_YEAR && month === TODAY_MONTH && day === TODAY_DAY) {
dateAbbreviation = 'today at ';
} else if (year === TODAY_YEAR && month === TODAY_MONTH && day === (TODAY_DAY - 1)) {
dateAbbreviation = 'yesterday at ';
}
if (dateAbbreviation) {
return dateAbbreviation + $filter('date')(timestamp, TIME_FORMAT);
} else {
return $filter('date')(timestamp, TIMESTAMP_FORMAT);
}
};
This code, like so much bad code, touches dates. This time, its goal is to output a more friendly date- like, if an event happened today, it simply says, "today at" or if it happened yesterday, it says "yesterday at". On the first day of the month, this fails to output "yesterday at". The bug is simple to spot:
if (year === TODAY_YEAR && month === TODAY_MONTH && day === (TODAY_DAY - 1)) {
dateAbbreviation = 'yesterday at ';
}
On September first, this only outputs "yesterday at" for September zeroth, not August 31st.
Now, that's a simple brainfart bug, and it could be fixed quite easily, and there are many libraries which could be used. But Daniel ran a git blame
to see who on the development team was responsible... only to find that it was nobody on the development team.
It probably isn't much of a shock to learn that this particular application has lots of little UI annoyances. There's a product backlog a mile long with all sorts of little things that could be better, but can be lived with, for now. Because it's a mile of things that can be lived with, they keep getting pushed behind things that are more serious, necessary, or just have someone screaming more loudly about them.
Sprint after sprint, the little UI annoyances keep sitting on the backlog. There's always another problem, another fire to put out, another new feature which needs to be there. The CTO kept trying to raise the priority of the little annoyances, and the line kept getting jumped. So the CTO just took matters into their own hands and put this patch into the codebase, and pushed through to release. As the CTO, they bypassed all the regular sign-off procedures. "The test suite passes, what could be wrong?"
Of course, it has its own little UI annoyance, in that it misbehaves on the first day of the month. The test suite, on the other hand, assumes that the code will run as intended. And the test suite actually uses the current date (and calculates yesterday using date arithmetic). Which means on the first day of the month, the test fails, breaking the build.
Unfortunately for Daniel and the CTO, this bug ended up on the backlog. Since it only impacts developers one day a month, and since it's pretty much invisible to the users, it's got a very low priority. It might get fixed, someday.