The (leap) day, the profiles died
On Monday, something weird happened. Without any changes, our CI status turned into a very dark red. Some contributors got scared because their Pull Requests were red and even the untouched stable release code suddenly failed. So… what happened?
Like all profile fields, the birthday field in a users profile is entirely optional. Not only can the users decide to not fill in the information, they are also free to enter only a day and a month, but not a year. Internally, the birthday field is a
date field. Obviously, you cannot store a time stamp without a year so we needed a distinctive dummy value. Using 1970 is pretty dangerous since people could actually be born on that year, so we used:
params["year"] = "1000" if params["year"].blank?
Later, when showing the birth date in the users profile, we simply check for that value
def birthday_format(bday) if bday.year == 1_000 I18n.l bday, format: I18n.t("date.formats.birthday") else I18n.l bday, format: I18n.t("date.formats.birthday_with_year") end end
Well, no. In our test suite, we do have a user which has a birthday and month, but no year. So the year gets replaced with the default year,
1000. Since our tests ran on Tuesday and we use the current month and day, the birthday was
1000-02-29. So, as it turned out, databases do not like that:
PG::DatetimeFieldOverflow: ERROR: date/time field value out of range: "1000-02-29"
Bummer. If we do the maths, year 1000 was not a leap year and apparently, databases check for that. Fun, eh? The solution is simple: use
1004 as a dummy year - or never run test suites on leap days. You decide.