Messing with Time: A New Value for Zero Time

3 min read

As of Dolt version 1.78.0, we have a new value for zero time. Zero time refers to datetime values converted from 0, false, and the timestamps 0000-00-00 and 0000-00-00 00:00:00. This is a breaking change that affects any previous values of zero time stored in Dolt, but we decided the benefits of a new value of zero time outweighed the risks of a breaking change.

So why did we mess with time? We’ll explain in this blog post.

Don't mess with time!

Previous Value of Zero Time#

Zero time in MySQL has the timestamp 0000-00-00 00:00:00. However, this timestamp is impossible to achieve in Go, the language that Dolt and go-mysql-server are written in, which requires non-zero values in the month and day fields of a timestamp. As a workaround, we used time.Unix(-62167219200, 0).UTC(), which has the timestamp 0000-01-01 00:00:00, to represent zero time in Dolt and go-mysql-server.

The Problems#

The problems with our previous value of zero time were exposed by a GitHub issue filed by TheoristCoder. While in MySQL, DAYOFMONTH(0) returned 0, Dolt was returning 1; this was then affecting the result of joins that joined on the result of DAYOFMONTH. Upon further investigation, many of other datetime-related function calls, such as MONTH(0) and DAY(0), incorrectly returned 1 instead of 0. This bug was due to us converting 0 to zero time and then extracting the day or month from the timestamp – since the date of zero time was January 1, we were returning 1 for the day and 1 for the month.

Our initial approach was to include a check for zero time in our datetime-related functions – if the input was zero time, we would return the correct value to match MySQL, rather than extracting values from the timestamp. But what if the input time had a timestamp of 0000-01-01 00:00:00? It would match our value of zero time, yet it’s a non-zero timestamp in MySQL, where MONTH and DAY should actually be returning 1. Furthermore, we saw that our value of zero time was causing bugs such as DATE(‘0000-01-01’) returning 0000-00-00 instead of 0000-01-01.

We realized then that in order to ensure the correctness of our datetime-related functions, we needed a new value for zero time that did not have a timestamp that conflicted with a non-zero timestamp in MySQL.

New Value of Zero Time#

We decided to set our new value of zero time to time.Date(0, 0, 0, 0, 0, 0, 0, time.UTC).

ZeroTime = time.Date(0 /* year */, 0 /* month */, 0 /* day */, 0 /* hour */, 0 /* min */, 0 /* sec */, 0 /* nsec */, time.UTC /* loc */)

Since Go requires non-zero values for the month and day, this underflows to have a timestamp of -0001-11-30 00:00:00. Negative years are not valid in MySQL, so this new timestamp for zero time does not conflict with any non-zero timestamps in MySQL.

With this new value of zero time, we did an audit of our datetime-related functions to ensure that the value they return for inputs of 0, false, and 0000-01-01 matched what MySQL returns. We are pleased to say that our datetime-related functions now match MySQL’s behavior.

There is an exception, and that’s with functions related to days of the week and inputs with dates before 0000-03-01. This is because Go considers year 0 a leap year where 0000-02-29 is a valid date while MySQL does not. Due to this extra day, the days of the week are off by one. For example, 0000-01-01 is a Sunday in MySQL but a Saturday in Go and Dolt. Year 0 is not a real year in the Gregorian calendar anyways so we don’t foresee this being a big issue.

What Breaks#

Any values of zero time stored in a Dolt database before the release of 1.78.0 will still have the old value of zero time, meaning they still have a timestamp of 0000-01-01 00:00:00, and will no longer be considered zero time. While we understand that this can be an inconvenience, this was a tradeoff we considered when it came to ensuring the correctness of our datetime-related functions.

If this change is causing any issues for you, feel free to file an issue on GitHub or visit our Discord server. We’d be happy to help!

JOIN THE DATA EVOLUTION

Get started with Dolt

Or join our mailing list to get product updates.