Need Help to convert DATETIME result into DATE on SQL Server

  • How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

  • Your issue is that the Date supplied '0001-01-01' results in out of range error, as it is less than the minimum DATE value accepted. 
    Minimum Date should be DECLARE @CurrentDate DATE = '1753-01-01'  or higher.

    -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    This thing is addressing problems that dont exist. Its solution-ism at its worst. We are dumbing down machines that are inherently superior. - Gilfoyle

  • Nexana - Monday, July 9, 2018 8:37 PM

    How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

    As Henrico suggests, this just isn't possible.   SQL Server simply will NOT work with any date value prior to January 1st, 1753.   As there's no normal practical use for such a date, most such attempts are the result of trying to come up with a clever way to manipulate dates with math or using character strings.   If you can supply your "why", we can probably find an alternate solution for you.

    Steve (aka sgmunson) 🙂 🙂 🙂
    Rent Servers for Income (picks and shovels strategy)

  • sgmunson - Tuesday, July 10, 2018 6:17 AM

    SQL Server simply will NOT work with any date value prior to January 1st, 1753. .

    Not sure what you're talking about.  The DATE datatype works just fine with '0001-01-01'.  In fact, it's the first boundary for DATE just like the first boundary for DATETIME is '1753-01-01'.

    If you're saying that DATETIME won't work with '0001-01-01', then I totally agree but SQL Server WILL work with that date given the correct datatype.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Nexana - Monday, July 9, 2018 8:37 PM

    How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

    The problem that you're having has to do with implicit casts.  The DATE datatype cannot do integer math like the much smarter and more useful DATETIME datatype can and so any time you do such integer math like when using "0" instead of '1900-01-01' converted to a date, you'll get a failure.  If we replace all your "0" integers and '-1" integers with the preconverted DATEs for those values, your code will work just fine. 


    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, CONVERT(DATE,'1900-01-01'), @CurrentDate), CONVERT(DATE,'1900-01-01') )AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, CONVERT(DATE,'1899-12-31'), @CurrentDate), CONVERT(DATE,'1899-12-31')) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, CONVERT(DATE,'1900-01-01'), DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),CONVERT(DATE,'1900-01-01')),120) AS FirstMondayOftheMonth


    Results:
    data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAiYAAABGCAYAAAD4pV81AAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAABM0SURBVHhe7d0PbBRXfgfwH1GUqFKuVaVWORpsKLIpSg2xYqry/59QSLlwLTob0hCCONXrpKIHls7iciCBJTgd594ZEipioyvHH98d2Cd6hYMQUf4YbJLWvjrGQYRdEWOb0hPX011CpEKPc9/vzZvZmfXu/N3Z3fF+P2jY+bPzPDv7duY3v/d2Z8Ktmx+NknD4h+1U/Tcv8igAAABAXjymHgEAAADyDoEJAAAAFAwEJgAAAFAwMvYx+fPn/lKNge6jDz9QYwAAABCGtIEJByU4CY+1cfM3aN+eb6spAAAAyLYxgQmCksw6/uVd2r59u5oCr1CvAADACQITDzgwuXjxIrImPiHjBAAATnwFJm998LgaS6+3V42kOPT3v1Vj0WQXmPzy1/8rHz/99FP5aParX31KsyrL1FTx0jNOCHwBACAT39/KqaqqSg7in5hjDJZlahjvPv74KVq0aBGtXLnSMsyePZu6H3yungVLlixRYwAAAGP5Dkx6e3uTg/gn5ljnpQzyKXaGj9GrlbOpImVovKKWB8Xlv3aMhtRkmDhr0vs/4iWL4dzgE86vHQAAACRfgQnnP1piVcZQ+/yofOxp0YbvvnLfGO96q4LEIqGV/7M3s55O971PA/pwsp7irVkOJkIOUG7cuEHxeJxGP+mhm7d+Q5/9Z0ItAQAAACdZ+YG1zz+3NlXo/SwePHggB/bEE9fkoyclpVTeP0i31WSha+3tlUEJJ4g++uhjenj9FD355A211Ac9i7TzqprBRujIa2JejrI/AAAAueQrMOGTLWcGenp66NKlS3IeP+oDa23tpffee49OnDgpp30ZHqL4zCk0WY6bm3pq6ciwfAYNtdUazT6vto2MzYhYpgfp4NZm6utvphVq3pj1A4hVVcl+JbFYFa1fv1YOTzz7EtXWPk/9D6dT128fl8PvfeGP1RouzJxBlTeHTK+ni872q3EAAIBxxnfGZPr06TRr1izZ4ZPxoz7cvfsn9PLL5XK84qW17rMGHDCoIEEOKwep7vAaKuUswdZztPyk3sSzjM5u5cDiKh1sKqP9qtmHmtrosioqvSm0YVc9VXKTkSzX6/r2RkZG6N69e3LgrMmP/uM3cj7vp7/9iz+QgQv3N1m9ereH4GQZLZ92ji6pQIxuDxJVr6JKNQkAADCe+ApMHjyYrsbG4qabiRP/S47H/+/35aNrlj4mHbRl5gk6z51fZZbgGu1eqQcsnPXgk3UJTRXPeYOzHZ3z6GjfFlqgleRS0PWtHj58SNevX5fD/fuX6Kn/7qTPHlN9TFpbxVAnR995p9ZTcLJocRmd7dSyOZcvJmj54ilyXHKbScow7/JOfV1tMDobW8oVg5518vD3AAAAvPIVmDx69O/ymzZ6083HTz1FJ0+eNJpvOGPy4x/HaeBUmxwe+Pq67CRaF1tF7Rf1/hWrtMyGMRygdSXiOYe16bpPqsVJcbfHjEfQ9a2mTp1qyRxxs44hFhNDCy1b9of0+oEDchYHJ65MFoHI2S6ZITp/cxktkm1bzEsmKX12aME2ta6ar3U25nKbqXxfcr6WoclW5goAACA93005/Nsk+gmYmydeeOEFo/mGm26qvlJFFRVaH4tHjx7Rw4cz1JoezF9INR2ddLlkHi3XsydMXrWLIEI+alftC7ZxhiVBg5TSYfb2IPWp0THSra83mfikf1VYNueIRwNnS+rqZPBSVdUr4hQRqLj9eRd+/eKV3b7SSe3TSsUrVDxlkjJkh8wZEF5fL5fqacN8njAJLXMFAACg8R2YmHHTjf7tG6P5ZpDo5u+0Phb+aSe881c4s9FMtFE/IfJVuzj5layhbzWQOlFW09nl22ldyRza0JCQJ0n53NaEtT+G/KYP92URgU3a9dXzAij93T0aekw10+i/YRJrIWppkYHLlmXHtaBEX+ZoEi1anqAW8VpqFs9R83RuM0np5l2lRrkv1bpGZsROGJkrAAAAje/AhJtw9OYbvemGv4HDTTeMm3p+3fNDObgigoSjskOqmXbC2y6v3OfQdsvJUD6BStceUPPep6NrJ42ZN3D4gFauUb5ejnZVn279IDhAM4ISEZwZ6jhjMksGJrvPrVYz3StduIyov4yWmrMYXjJJVzJlh8poih6M6dklmaFppoOpP27n5e8FzDwBAEBx8h2YvPnmm9TYeIp+8IN/EMFJq3x8++1Oamn5JznwvCNHjhiDr98xiTIRlLTSrOQ3klpa6N7OM3T//n165c++6yFbonBgNaaJxEMmab6L7NLGE8lyd9VT3ChXNfF4+XtZyDwBAEDxwd2FPbC7iV/XB4/T88+P0s9/PsHSd+TJgRvy90w4W8J6at+h1w+8TrGqFhm8Hfr+V+X8gnZlN1VcXEgD21KbkbzB3ZkBAMBJVvqYgIa/bdPd/bYMOPRB96O/+zdqjbXIwIWDkkC/CBu6q9SoZ1FkJiVBW9YHC0oAAADcQMbEAz9X/D19CdnElUkkMiZZgowJAAA4QcYkZLMqy2TwkWkAAACAJGRMPNCv+C9cuKDmAAAAQDYhMAEAAICC4RiYcJYAAAAAIBdcBSbcfAEAAAAQNteBSdT7VSxZsgR9QyBnUN8gG1CPoNhwnfcUmES170lqcBXV1wHRgPoG2YB6BMVGr/P4urBHQ221VKHuC1OUzHcjlgNu2AcBoD7lRNEct/hXqvNRh/zUY7VOY+o9yaIixO1HYAIe8N2Im4kaOpI3SRxz/x4At1CfYDxAPc42BCZsTLSrD2OvMLS7ESfvbpw1chsyXNGk277XjtGQWpwVKX/j1bYRtcBkeIjiNIOWL0xzF2Y364fJbv8VGrWvQr1SstsfKe+VHFCfrOz2X6FI9z7KoRCOW+q2FpZ6pebtvKqmIyAr9TiMepSj/ZunzwECE5OafXq0qw8hfJADSG5fB22hZlqRrZMJVz4R8Zcb5Yvxpmr3J4Og60NeoD6NDwV93OofpNtqlK50UrsajYQo1MMo718bCExcUZGoMaS0H3IFFvP5CvjyzuTzLFfEsu3TXIYehaqyxQegj67R7pXJ52T+AEyidbvqqbK/mQ6qv6G1ISfXTW7jCB15TUyniaLlOuJkdOSQ+NvVzbR9vlpAc2hDwwzqa2rTylCvL902crmXXa5v3h9yP5m2KfP2C7b71/3+s/4Nt+Xnh+3+YKhPqE+O8n3cWkU11SfovCpv6HZCTK/SJgyqPhnlp9uP1udY96N5mdg24yytyV893u3hc2j3+mzqWaj718txxH77/UBg4soc2q5fjexLfeOT2jfOpvOLteftr1YzJfEmbzyRcmWjX9Wosk+KEwPNoC0nk885ujZNalBXMo+WzySK31aVZPJX6bRRdjPV0AlqkRVInHRiYps7Ok0Vml2lg03XqCZWSrc6iCr/1HqJVbpwmdieBA3yQahkDR3NsI0D24jOO63vRsbtT0q/f93tP/5wr2gqo/1q2X7xgX4jJUOQ+f3LA9v9gfrkCPVJyP9xa+niVdR+kU/+I3TpbJmY1uZr+IRWTbup3niv0u/HaroV05afFoFB+8bkyfXyTvP624nOnlBLlLzV4y2uP4d2r8+pnoW3f90fR+y23y8EJib8AdWjPj+RX2VDhxFdL9j2vinSLqGp4qDf3mqtENnQ94l2pC6dP4dK5RjT/p6+jOavpS0zrQfmobZ/pvaZ9bRBbWP55HQnrWt0K+UKJJOg69tuv5J5/zrRDjaVDWuNDmkLxAfakgYV/Jefffb7A/XJSTHVp4I+bs1fSDV88h/uorPTFlo7hPK8fnHS27XGeK8WrBcnQlPmjpm3r3RymTYiXZVBbE1MX18FGyb5rsdu2L0+x3oW6v51J+j66SAwMUltq01+QN1JX4mZ+MAcFmXuIvqmfgBJk0L0IxnRq9SbHESU3K9mS9oH1khByuiarwqSFda4UraYQVMnq1EHQde3335N5v3rQHZOEwekpmpVvhjElSClXIH7Lj8UDu8n6pOD4qlPhX3cmkNLxVV6y9ZzVL54jpqn3B6kPjVqKCmlcjWqy7h9qtOpfZ3Ibz12w/71OdWzEPevS2HUcwQmuWRO/XXU27T5uyCjYb1S8IevnuIictUOTh3iSkB7msF8dXClTab3tKsCrthjryaHOs+JSl1GU6yZzDT8rD9CgzfVqORi+4NQH0aO7M0H8ELr3Jzkcn+gPimoT6EKWM/4Kr+vv4yWpgZMk6dQpRo1qJOxe3bZi3zW4yxwWc/C3b/5gcAkF64cs37dSlU4S6Qp57lNEYoPHHdKMqUcWbK8Ybo15gpRvzpopFdbT1iuCmR6TxxwjBTw8DH6ZkoK0Y7j+ur16lcfsl3Y9go23fY7sN1/6iBjXBlFQ8b9gfqE+pQL2apn87eIk2ma3/WQ/Zqu0e6tyaYi2fE5pR5mpPpFaX0sBO7MKTMKVvmqx5Knz2Eql/UsrP3LAm2/fwhMcmLQ2mNbRfHWlKvW49vSXpySNk0uq6f26mYaOKx/iFLX7aSl3NlNfKgs33Pn9khRyfqMqwKFr4jE1VBcX1+cpPjHgmw7S5qlWZ+/YpdcX+/NrqUkuaOdtZOdy+23Zb//uO38dEOC3tCXySH33883s2yrHPROY077A/WJtw/1KWzZqWeZcVNRh/ZVdbXuGx2raL9RD52I9fnbZPy+8vpbib7F77Mhz/VYCrJ/gtazoPuXBdt+v3CvnKKipTZJHOS9tkN7wlcu4kPMkflpTx+C8aF46hvqU5hw3MqVHNVjcIR75RSh1B7noeErDW7PzeaPdkHBQX2C8SBn9RhcQ2BSBPQfT5Lfh8/ZFSenEd83NQ/AeIH6BONBfuoxuIHApAhwO6XWmxs3loLgUJ9gPEA9Llye+pg0NjaqudFjbquN8uuAaEB9g2xAPYJiw3XedWAyHvAHfMmSJWoKIFyob5ANqEdQbFwHJvv2fFvNiTZuU+T0HR7xmItHAADwxlNgwsuiiq84+DV8+Nkv1RyAcK1d8BKNjsqPF4BvfDyO8rEXwAuu754DE/OyqDC/Br6Sbbt8Si0BCM9zX/gjnFAgMAQmUEy4vhfdt3IQlECucBAMAADeZDcw4V9oLPCfZeb0upMPm16Sz5NDU4+amxR0uXTnp7Rjwdfp3Ttq2oOol18s3PYxOVM3gSZMUEPdGTU3KehyKbGX5k2YR3sTatoD2/LP1CWX8TBvL3n6E27XD7D9xSLS9UhXwOVD7mQlMNF/qIbvJTDmNssFxilj8ov2r9N3btXS98Tz2i4foHW3dtCO9rtqafDlxkn/5QO+7vIY9fKLiZuMSWLvPFoxsIfio6M0OhqnPQMraJ7pqBl0uXGwLt9M3WqeF07lU3mDWsbDaYp1b6b1Xo76DusH3f5iEfV6VOjlQ25lITAZocnr1Q/VWG6gVJj4pJpZD5166wYtXf/X9LScnkgvrn+R4m/9hD6U00GX36UvvsInfDE0vSjneBP18ouLc8bkDDVt7qbYtk1UJqfLaNO2GHVvbhJLWNDlCXHe5wO1GE7H5BxvnMoXysrUMlZOz85Vo27Zrh90+4tF1OtRoZcPuZaFwGQSlZao0QiwzZjcuUPDNJ2eMb+ekhJxuByku9xkEXS5ONE//Yyc60/Uyy8yjhmTxE0aoLn0LN9LXlf+rJgzQDf5Yi/ocnGAFud9/xzLT5H4GR3vnkurv+Tzj45ZP+D2F4vI16MCLx9yrug6v9pmTIaHMzRP3KA73G8m6PKgol5+kXHMmMSvZ0grd9N1fiOCLg/KZfmcRtfS5MdpdbyLNnk8CQRdv+iNk3rkW9jlQ84VXWDi1Mck37iPh+zDYRrMfTyCCrt8SIrCt3KMoMA0mNvm3Sjb1KWlyeOr6Xi5dX035dutD9GQjXpkJ+zyobAgY2Immy3SUc0bQZe78HTNP2p9OEzDjpqJ2sIIlA9JjhkTmW5OR6Wlgy53wQgKTEOXnrLwWn7ZJtoWE9epx39G+inDtvxUadYHF8ZbPUoj7PKhsCBjYvbMM1SS2mwhmzem0ETuWxF0eVBRL7/IOGZMyqZRRWq6WaalK2gaH3ODLg/KR/nlnnu/WgVdvyiNw3rkSdjlQ84hY2Ixi1762nQ6f+in9As5fZfePfQulX/tK/ScnA66PKiol19cnL+V81fUsGcute7Uf7sjQXt3ttLcPQ1iCQu6PCiP5Sf20vrN3TR39ZfI1/kg6PpFa5zVI8/CLh9yLQs/SX+VGivrqV1NWcysp9OH11CpmswX82twc68c/q2O7/yrmvjyDmprmKUmNP6X99D3F+yg82rKoqKWvrdf/5quvaiXXyw4COaUsxP+jYUVrWoidppGW6yHU//Lz1DdhBWkL7KYu4fiXfrXK+3Z/n3+gTRjoZBm+2zZrp+d7Y86tz9JH916FI3yITe4vuNeOQAhwb1yIBvcBiYA4wHXd/QxAQhJFL6VAwBQaNDHBCAkzn1MAAAgFTImACFBxgQAwDvPfUwaGxvVkmhBHxPINfQxgWxAHxMoJlzfPQUmGzd/Q82NJn4Nbr6VA5ANbr+VA2AHgQkUE8+ByXjAGRNu+8cjHnPxCAAA7nEM4jowuXDhgpoDAAAAEAai/wcIJeSLIpsVcAAAAABJRU5ErkJggg==

    You can also cheat on the notation a bit to make it simpler (and possibly a bit slower).


    DECLARE @CurrentDate DATE = '0001-01-01'
           ,@0 DATE           = '1900-01-01'
           ,@Minus1 DATE      = '1899-12-31'
    ;
    SELECT
            DATEADD(QQ, DATEDIFF(QQ, @0, @CurrentDate), @0)AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, @Minus1, @CurrentDate), @Minus1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, @0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),@0),120) AS FirstMondayOftheMonth
    ;

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Just a quick note, DATE data type is stored as 3 byte little-endian, which has number of days after 0001-01-01. This means that i.e. 0001-02-01 = 0x1F0000 when in the right byte order is should be 0x00001F. It is therefore obvious that any direct numerical calculation or manipulation of the DATE data type is a futile exercise.
    😎

    Here is an example of the first day of each of the first 13th moths

     N    DT            RAW_BIN     BYTE3   BYTE2   BYTE1   REV_BIN    INT_VAL
     0    0001-01-01    0x000000    0x00    0x00    0x00    0x000000    0
     1    0001-02-01    0x1F0000    0x00    0x00    0x1F    0x00001F    31
     2    0001-03-01    0x3B0000    0x00    0x00    0x3B    0x00003B    59
     3    0001-04-01    0x5A0000    0x00    0x00    0x5A    0x00005A    90
     4    0001-05-01    0x780000    0x00    0x00    0x78    0x000078    120
     5    0001-06-01    0x970000    0x00    0x00    0x97    0x000097    151
     6    0001-07-01    0xB50000    0x00    0x00    0xB5    0x0000B5    181
     7    0001-08-01    0xD40000    0x00    0x00    0xD4    0x0000D4    212
     8    0001-09-01    0xF30000    0x00    0x00    0xF3    0x0000F3    243
     9    0001-10-01    0x110100    0x00    0x01    0x11    0x000111    273
    10    0001-11-01    0x300100    0x00    0x01    0x30    0x000130    304
    11    0001-12-01    0x4E0100    0x00    0x01    0x4E    0x00014E    334
    12    0002-01-01    0x6D0100    0x00    0x01    0x6D    0x00016D    365

    The highest value accepted is 9999-12-31, numerical value of 3652058 which in binary format is 0x37B9DA.

  • Eirikur Eiriksson - Saturday, July 14, 2018 1:30 AM

    Just a quick note, DATE data type is stored as 3 byte little-endian, which has number of days after 0001-01-01. This means that i.e. 0001-02-01 = 0x1F0000 when in the right byte order is should be 0x00001F. It is therefore obvious that any direct numerical calculation or manipulation of the DATE data type is a futile exercise.
    😎

    Here is an example of the first day of each of the first 13th moths

     N    DT            RAW_BIN     BYTE3   BYTE2   BYTE1   REV_BIN    INT_VAL
     0    0001-01-01    0x000000    0x00    0x00    0x00    0x000000    0
     1    0001-02-01    0x1F0000    0x00    0x00    0x1F    0x00001F    31
     2    0001-03-01    0x3B0000    0x00    0x00    0x3B    0x00003B    59
     3    0001-04-01    0x5A0000    0x00    0x00    0x5A    0x00005A    90
     4    0001-05-01    0x780000    0x00    0x00    0x78    0x000078    120
     5    0001-06-01    0x970000    0x00    0x00    0x97    0x000097    151
     6    0001-07-01    0xB50000    0x00    0x00    0xB5    0x0000B5    181
     7    0001-08-01    0xD40000    0x00    0x00    0xD4    0x0000D4    212
     8    0001-09-01    0xF30000    0x00    0x00    0xF3    0x0000F3    243
     9    0001-10-01    0x110100    0x00    0x01    0x11    0x000111    273
    10    0001-11-01    0x300100    0x00    0x01    0x30    0x000130    304
    11    0001-12-01    0x4E0100    0x00    0x01    0x4E    0x00014E    334
    12    0002-01-01    0x6D0100    0x00    0x01    0x6D    0x00016D    365

    The highest value accepted is 9999-12-31, numerical value of 3652058 which in binary format is 0x37B9DA.

    And yet the DATETIME is stored as the number of 1/300ths of a second and both the direct integer math and the direct temporal math still works.  The problem isn't with the underlying storage method.  The problem is with the stupid, non-ANSI way MS wrote the code for the functions that handle (or I should say, don't correctly handle) the DATE and other supposedly "more advanced" datatypes, which are actually a throwback to the dark ages IMHO.

    Ironically, MS is aware of that fact because, in a vain attempt to fix their shortsightedness, they came out with DATEDIFF_BIG instead of fixing things to allow for the ANSI standards of being able to do things like Period = EndDateTime - StartDateTime and EndDateTime = StartDateTime + Period which, as you know, the DATETIME datatype actually does quite nicely if you know how to format the Period.  The following article demonstrates such a thing using DATETIME.  The same methods will not work with the "newer, improved" (whatever you want to call them... I call them "crippled") temporal datatypes.
    http://www.sqlservercentral.com/articles/T-SQL/103343/

    Sorry to rant but considering all of the temporal information and reporting required of databases in general, the "crippled" datatypes are a horrible oversight by MS.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff, where should I start on this? Not translating the binary values, in the right order, caveats on the ranges covered, unsigned datatype as a base?
    😎

    Datetime is a float  constructed value, makes the arthimetris straight forward, the 2008 introduced data types need some work!
    Posted here few years back a test harness and the new types were around 50% slower

  • Jeff Moden - Friday, July 13, 2018 10:00 PM

    Nexana - Monday, July 9, 2018 8:37 PM

    How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

    The problem that you're having has to do with implicit casts.  The DATE datatype cannot do integer math like the much smarter and more useful DATETIME datatype can and so any time you do such integer math like when using "0" instead of '1900-01-01' converted to a date, you'll get a failure.  If we replace all your "0" integers and '-1" integers with the preconverted DATEs for those values, your code will work just fine. 


    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, CONVERT(DATE,'1900-01-01'), @CurrentDate), CONVERT(DATE,'1900-01-01') )AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, CONVERT(DATE,'1899-12-31'), @CurrentDate), CONVERT(DATE,'1899-12-31')) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, CONVERT(DATE,'1900-01-01'), DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),CONVERT(DATE,'1900-01-01')),120) AS FirstMondayOftheMonth


    Results:
    data:image/png;base64,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

    You can also cheat on the notation a bit to make it simpler (and possibly a bit slower).


    DECLARE @CurrentDate DATE = '0001-01-01'
           ,@0 DATE           = '1900-01-01'
           ,@Minus1 DATE      = '1899-12-31'
    ;
    SELECT
            DATEADD(QQ, DATEDIFF(QQ, @0, @CurrentDate), @0)AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, @Minus1, @CurrentDate), @Minus1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, @0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),@0),120) AS FirstMondayOftheMonth
    ;

    @jeff: Replacing the '0' with the pre-converted DATEs worked fine without even compromising speed. Thank you so much 😀

  • Eirikur Eiriksson - Saturday, July 14, 2018 12:34 PM

    Jeff, where should I start on this? Not translating the binary values, in the right order, caveats on the ranges covered, unsigned datatype as a base?
    😎

    Datetime is a float  constructed value, makes the arthimetris straight forward, the 2008 introduced data types need some work!
    Posted here few years back a test harness and the new types were around 50% slower

    Just to be sure of what you're talking about... are you talking about the datatypes for the storage of DATETIME or just the methods to do the direct temporal calculations with DATETIME?  I used to think that DATETIME was a float (despite what they said in BOL because it behaved like one for accuracy) but someone proved to me that Datetime is patently NOT a float constructed value.  He showed me the values stored on a page and they really were INTs and I proved their content by manually doing the date math for the stored values.   It is, in fact, comprised of two integers, the first being the number of whole days since 1900-01-01 and the second being the second being the number of 300th's of a second since midnight.

    As good as that is, I'm still disappointed a bit in DATETIME.  It, indeed, would have been great, if DATETIME had been stored as DECIMAL days where time was the fractional part of the decimal but it was invented long ago when disk space was a premium and every byte counted.  Heh... as you know, it still smokes the newer datatypes for functionality.

    As for the "new" types being 50% slower, you've piqued my interest.  Slower doing what? I've no real hint there because I avoid them like the plague.   Do you mean any form of date/time math using the date/time functions built into SQL server or joins or comparisons or ???  If you have a link for that post from a few years back, I'd love to see it because you're one of the folks that does know how to put together some excellent performance tests.  And, if that link contains your typical well thought out tests, THAT would make an excellent article for you to submit!

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Nexana - Saturday, July 14, 2018 5:12 PM

    Jeff Moden - Friday, July 13, 2018 10:00 PM

    Nexana - Monday, July 9, 2018 8:37 PM

    How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

    The problem that you're having has to do with implicit casts.  The DATE datatype cannot do integer math like the much smarter and more useful DATETIME datatype can and so any time you do such integer math like when using "0" instead of '1900-01-01' converted to a date, you'll get a failure.  If we replace all your "0" integers and '-1" integers with the preconverted DATEs for those values, your code will work just fine. 


    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, CONVERT(DATE,'1900-01-01'), @CurrentDate), CONVERT(DATE,'1900-01-01') )AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, CONVERT(DATE,'1899-12-31'), @CurrentDate), CONVERT(DATE,'1899-12-31')) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, CONVERT(DATE,'1900-01-01'), DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),CONVERT(DATE,'1900-01-01')),120) AS FirstMondayOftheMonth


    Results:
    data:image/png;base64,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

    You can also cheat on the notation a bit to make it simpler (and possibly a bit slower).


    DECLARE @CurrentDate DATE = '0001-01-01'
           ,@0 DATE           = '1900-01-01'
           ,@Minus1 DATE      = '1899-12-31'
    ;
    SELECT
            DATEADD(QQ, DATEDIFF(QQ, @0, @CurrentDate), @0)AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, @Minus1, @CurrentDate), @Minus1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, @0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),@0),120) AS FirstMondayOftheMonth
    ;

    @jeff: Replacing the '0' with the pre-converted DATEs worked fine without even compromising speed. Thank you so much 😀

    My pleasure.  Thank you for the feedback.

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Nexana - Monday, July 9, 2018 8:37 PM

    How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

    That is a valid DATE data type display string. There should be no need to build it from pieces like a 1960's COBOL expression. Things like the firs and  last dates in a quarter ought to be in a Calendar table.

    Please post DDL and follow ANSI/ISO standards when asking for help. 

  • jcelko212 32090 - Sunday, July 15, 2018 4:41 PM

    Nexana - Monday, July 9, 2018 8:37 PM

    How can I convert the result into a DATE datatype as '0001-01-01' isn't supported with DATETIME? I've tried DATETIME2 but not working and the StartDate needs to be '0001-01-01'. Any help with this is highly appreciated.

    DECLARE @CurrentDate DATE = '0001-01-01'

    SELECT
            DATEADD(QQ, DATEDIFF(QQ, 0, @CurrentDate), 0) AS FirstDayOfQuarter,
            DATEADD(QQ, DATEDIFF(QQ, -1, @CurrentDate), -1) AS LastDayOfQuarter,
            CONVERT(VARCHAR(10), DATEADD(WEEK, DATEDIFF(WEEK, 0, DATEADD(DAY, (6-DATEPART(DAY, @CurrentDate)), @CurrentDate)),0),120) AS FirstMondayOftheMonth

    That is a valid DATE data type display string. There should be no need to build it from pieces like a 1960's COBOL expression. Things like the firs and  last dates in a quarter ought to be in a Calendar table.

    Calendar tables are certainly a convenience but the formulas can be quicker and take no reads like a Calendar table would.  Since they don't rely on a Calendar table, they also have no dependencies and can be used in any database.

    Heh... Imagine the conversation...
    Employee:  I can't do my job!  There's no Calendar table in this database!
    Manager:  We don't own that database so we can't add a Calendar table to it.
    Employee:  Ok.  I'll get the data from the Calendar table in one of our databases.
    Manager:  Can't do that.  We're not allowed to go to another database for data.
    Employee:  I can't do my job!  There's no Calendar table in this database!

    Yeah... lemme help you find another job.  Burger King ok with you? 😉

    All hail the 1960's COBOL expressions!!!  A lot of the "Black Arts" of SQL Server are actually just tried and true "Old Arts" that will work well forever. 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

  • Jeff Moden - Friday, July 13, 2018 9:45 PM

    sgmunson - Tuesday, July 10, 2018 6:17 AM

    SQL Server simply will NOT work with any date value prior to January 1st, 1753. .

    Not sure what you're talking about.  The DATE datatype works just fine with '0001-01-01'.  In fact, it's the first boundary for DATE just like the first boundary for DATETIME is '1753-01-01'.

    If you're saying that DATETIME won't work with '0001-01-01', then I totally agree but SQL Server WILL work with that date given the correct datatype.

    As always, you educate me in new ways....   I was unaware that the DATE data type would support such, but the DATETIME does not, so I had once again made an assumption that turns out to have been unwarranted, as I had always known that 1/1/1753 was the low end on DATETIME.    However, from a practical perspective, just what on earth value is there in using such values for a DATE data type?   Certainly not the accurate measurement of the historical timeline...  And I am an absolute stickler for using the right data type for the right reason.   So maybe my saying SQL Server won't work with those "date values", I'm at least "historically accurate" ?   Anyway, thanks for keeping me up to date....

    Steve (aka sgmunson) 🙂 🙂 🙂
    Rent Servers for Income (picks and shovels strategy)

  • sgmunson - Monday, July 16, 2018 7:10 AM

    Jeff Moden - Friday, July 13, 2018 9:45 PM

    sgmunson - Tuesday, July 10, 2018 6:17 AM

    SQL Server simply will NOT work with any date value prior to January 1st, 1753. .

    Not sure what you're talking about.  The DATE datatype works just fine with '0001-01-01'.  In fact, it's the first boundary for DATE just like the first boundary for DATETIME is '1753-01-01'.

    If you're saying that DATETIME won't work with '0001-01-01', then I totally agree but SQL Server WILL work with that date given the correct datatype.

    As always, you educate me in new ways....   I was unaware that the DATE data type would support such, but the DATETIME does not, so I had once again made an assumption that turns out to have been unwarranted, as I had always known that 1/1/1753 was the low end on DATETIME.    However, from a practical perspective, just what on earth value is there in using such values for a DATE data type?   Certainly not the accurate measurement of the historical timeline...  And I am an absolute stickler for using the right data type for the right reason.   So maybe my saying SQL Server won't work with those "date values", I'm at least "historically accurate" ?   Anyway, thanks for keeping me up to date....

    Thanks for the feedback, Steve.  You'll get no argument from me on the subject of accuracy when it comes to dates prior to 1753.  The Gregorian calendar came to be the standard across many years with seemingly one country or area at a time slowly adopting it.  There's also the subject of the inherent date errors that built up over time with the Julian and other calendars.  Heh... then there's the subject of why there is no year 0000. 😉

    --Jeff Moden


    RBAR is pronounced "ree-bar" and is a "Modenism" for Row-By-Agonizing-Row.
    First step towards the paradigm shift of writing Set Based code:
    ________Stop thinking about what you want to do to a ROW... think, instead, of what you want to do to a COLUMN.

    Change is inevitable... Change for the better is not.


    Helpful Links:
    How to post code problems
    How to Post Performance Problems
    Create a Tally Function (fnTally)

Viewing 15 posts - 1 through 15 (of 40 total)

You must be logged in to reply to this topic. Login to reply