Oh, these databases: Sybase (ASE) and datetime

    Hi, Habr!
    In fact, a post about one line in the documentation, as it turned out. But it was unexpected, so I decided to share what I found with you.

    The new designer, the new tables, decided to file tests for them, and, in general, was surprised when the first test I wrote broke on the fact that the object that I threw into the database is not equal to the same object removed from the database.
    After repeated launches, it became clear that the milliseconds did not converge. Well, that is, you take such an object, you say “here’s new Date () for you, and now write it in the database. Now read on ID. And now equals. What the fuck? O_o. " Something like this. And, yes, all of a sudden a test can succeed.
    After some digging, an interesting thing turned out.
    The documentation on the Sybase website contains a description of the data types used. For the datetime data type, in ASE version 15.0, there was only this:
    if the link breaks, then Adaptive Server Enterprise 15.0> Reference Manual: Building Blocks> System and User-Defined Datatypes> Date and time datatypes , which says that
    datetime columns hold dates between January 1, 1753 and December 31, 9999. datetime values ​​are accurate to 1/300 second on platforms that support this level of granularity. Storage size is 8 bytes: 4 bytes for the number of days since the base date of January 1, 1900 and 4 bytes for the time of day.
    Once again, I draw attention to the fact that
    datetime values ​​are accurate to 1/300 second
    Days are stored in high 4 bytes, and time of day in low 4 bytes. In days 24 hours * 60 minutes * 60 seconds * 1000 milliseconds = 86_400_000 milliseconds in days, a number that completely fits into 4 bytes (0x5_26_5C_00). Even for a sign bit there is a place. Someone, please share how you need to store the time of day so that it does not fit?
    For ASE 15.7, the description of how this data type behaves is slightly extended.
    Adaptive Server Enterprise 15.7> Reference Manual: Building Blocks> System and User-Defined Datatypes> Date and time datatypes
    datetime columns hold dates between January 1, 1753 and December 31, 9999. datetime values ​​are accurate to 1/300 second on platforms that support this level of granularity. The last digit of the fractional second is always 0, 3, or 6. Other digits are rounded to one of these three digits, so 0 and 1 round to 0; 2, 3, and 4 round to 3; 5, 6, 7, and 8 round to 6; and 9 rounds to 10 ... Storage size is 8 bytes: 4 bytes for the number of days since the base date of January 1, 1900 and 4 bytes for the time of day.
    That is, you record an object with one time stamp, and you read "almost the same, sometimes even exactly the same." You can even go a little bit into the future (for a millisecond) if a nine falls out.
    Well, this is documented, so this is not a bug, but a feature, there are no complaints against Sybase.
    For all that, ASE 15.7 has
    bigdatetime columns hold dates from January 1, 0001 to December 31, 9999 and 12: 00: 00.000000 AM to 11: 59: 59.999999 PM. Its storage size is 8 bytes. The internal representation of bigdatetime is a 64 bit integer containing the number of microseconds since 01/01/0000.

    The moral of this post: RTFM and use bigdatetime, Luke!

    Also popular now: