@Rancor I could reproduce the problem with CM13. It’s funny 
For instance, 1900-02-13 is UNIX time -2205273600 (2205273600 seconds before 1 Jan 1980 00:00 UTC). Because Android stores dtstart
in milliseconds, it’s -2205273600000. When the content provider is passed this value for the dtstart INTEGER
SQLite field, it becomes 2089670400000 (Mar 21 2036 00:00 UTC), probaby because of the overflow of a int
value in the provider: 32-bit signed int
has a range from -2147483648 to +2147483647. If you scroll to Mar 2036, you will see this birthday (note that not only the year is incorrect, but the date is 21 Mar instead of 13 Feb because of the overflow).
However, if you use 1902-02-13, the dtstart
inserted by DAVdroid is -2142201600000 [ms UNIX time]. This is now within the range of int
and will be processed correctly.
Because DAVdroid provides the correct dtstart
values to the Android calendar provider and SQLite is perfectly capable of storing up to 8 bytes in INTEGER
values, there must be an overflow problem in the Android calendar provider, probably caused by using int
instead of long
somewhere. If you want to exactly identify or fix this problem, please work with the Android calendar provider source code. It’s possible that this bug was introduced with Android 5 or 6.
Edit: the calendar provider uses android.text.format.Time
(which is deprecated) to check/fix all-day date/time values. Its documentation states:
For historical reasons when performing time calculations all arithmetic currently takes place using 32-bit integers. This limits the reliable time range representable from 1902 until 2037.
So, only dates between 1902 and 2037 will be processed correctly and it’s really a 32-bit problem.
To fix the problem, Android calendar provider would just need to use java.util.Calendar
instead of android.text.format.Time
. I have created an Android bug report for this: https://code.google.com/p/android/issues/detail?id=225154