{"id":1769,"date":"2014-03-06T00:00:00","date_gmt":"2014-03-06T00:00:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/on-handling-dates-in-sql\/"},"modified":"2021-09-29T16:21:39","modified_gmt":"2021-09-29T16:21:39","slug":"on-handling-dates-in-sql","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/sql-server\/t-sql-programming-sql-server\/on-handling-dates-in-sql\/","title":{"rendered":"On Handling Dates in SQL"},"content":{"rendered":"<div id=\"pretty\">      &#8220;I&#8217;ve been on a calendar, but  I&#8217;ve never been on time.&#8221;<br \/>&#8211;Marilyn Monroe  <\/p>\n<p class=\"start\">The most international of all units of  measurement on earth is the Common Era Calendar. This used to be known as the &#8220;Gregorian Calendar&#8221;, &#8220;Western Calendar&#8221;  or &#8220;Christian Calendar &#8220;when it was issued by Pope Gregory in 1582. And the original company is still in business. There  have been no upgrades since then, unless you want to count adding local names for the months. For example,  <a href=\"http:\/\/en.wikipedia.org\/wiki\/Czech_months\">Czech months <\/a> &#160;are  of Slavic origin (<i>&#197;&#195;&#173;jen<\/i>), whereas the Slovak months are of Latin origin (<i>Okt&#195;&#179;ber<\/i>),  but most languages use the Latin roots. But I am in database, so I only care about the subset of ISO-8601 display  formats used in my language. The only use of the term   &#8216; field &#8216;  in SQL is for the parts of a timestamp (<code>YEAR, MONTH, DAY, HOUR, MINUTE, SECOND<\/code> ); for this article, all I care about is the <code>DATE<\/code> set of fields (<code>YEAR, MONTH, DAY <\/code> ). Do not panic,  this subset is good enough for most commercial work. Those of you who deal with museums, talk to me off line.   <\/p>\n<p class=\"MsoPlainText\"> Today, every SQL implementation has a <code>DATE<\/code> data type, but the functions available for them vary quite a  bit. The most common ones are a constructor that builds a date from integers or strings; extractors to pull out the  month, day, or year; and some display options to format output. Do not mimic 1970&#8217;s COBOL and format data for display,  using a  proprietary vendor feature.  <\/p>\n<p class=\"MsoPlainText\"> In Standard SQL, the constructor is &#8220;<code>CAST (&lt;string expression&gt; AS DATE)<\/code>&#8221; for a string expression. Hey, we  have this in T-SQL now! In Standard SQL, the <i>only<\/i> ISO-8601 format &#8220;<code>yyyy-mm-dd<\/code>&#8221; allowed for date values. Hey, we  have this is how T-SQL displays by default in the new <code>DATE<\/code>,<code> TIME<\/code> and <code>DATE TIME2(n)<\/code>! Do you think that Microsoft is trying  to catch up? The ANSI Standard also has &#8220;<code>DATE (&lt;string expression&gt;)<\/code>&#8221; option lacking in T-SQL, but that is simple  syntactic sugar.  <\/p>\n<p class=\"MsoPlainText\"> The ISO-8601 Standard has other date and time formats which are not ambiguous and could be added to the  strings recognized by SQL. But we had to make a decision for the SQL Standard, so that we have one and only one way to  work with dates. This avoids problems like confusing the British (&#8220;<code>dd\/mm\/yy<\/code>&#8220;), American (&#8220;<code>mm\/dd\/yy<\/code>&#8220;) and other national  traditional shorthands. This format is also embedded in lots of other ISO Standards, hardware counters and anything that  has to be sorted in temporal order. We picked the most readable, most universal one we had.  <\/p>\n<p class=\"MsoPlainText\"> SQL Server still has the 1970&#8217;s Sybase\/UNIX convert() string function. This is because when it was written,  we did not know how to use tiered architectures. Client\/Server was brand new! We had decades of monolithic COBOL as the <i>only<\/i> programming model (yes, I am that old). This means that all the display formatting is mixed in the the other  code for data retrieval, computations, etc. To accommodate this, Sybase added convert() with local, non-standard  displays for dates. There was no concept of independent presentation layers, separated from the database layer, doing  local translations, computations and all the display work.  <\/p>\n<p class=\"MsoPlainText\"> Sybase also added <code>MONEY<\/code> as a data type to put punctuation marks (currency symbol, comma, decimal point) in  currency display. <code>MONEY<\/code> is another issue; it does not do correct math, does not port and has illegal precision for many  GAAP and EU regulations. This was done with a <code>PICTURE<\/code> spec in COBOL (http:\/\/en.wikipedia.org\/wiki\/Picture_clause), if  you want to see where Sybase got this.  <\/p>\n<p class=\"MsoPlainText\"> The ANSI\/ISO extractor  for is the function<code> EXTRACT(&lt;extract field&gt; FROM &lt;extract source&gt;) <\/code>  <\/p>\n<p class=\"MsoPlainText\"> The extract field options  for dates are a little easier to see this in a table <\/p>\n<table>\n<tbody>\n<tr>\n<td valign=\"top\">\n<p class=\"style2\"><b> \t\t\tMeaning of &lt;primary  \t\t\tdate field&gt; <\/b><\/p>\n<\/td>\n<td colspan=\"2\" valign=\"top\">\n<p class=\"style2\"><b> \t\t\tKeyword <\/b><\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"style2\"> \t\t\tYear in Common Era  \t\t\tCalendar (returns 0001-9999) <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"style2\"> \t\t\t<code>YEAR<\/code>  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"style3\"> \t\t\tMonth  \t\t\twithin year (returns 01-12) <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"style3\"> \t\t\t<code>MONTH<\/code>  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"style3\"> \t\t\tDay within  \t\t\tmonth (returns 01-31) <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"style2\"> \t\t\t<code>DAY<\/code>  <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoPlainText\"> The obvious ordering is from most significant to least significant: <code>YEAR<\/code>,<code>MONTH<\/code>  <code> <\/code> and <code>DAY<\/code> .  <\/p>\n<p class=\"MsoPlainText\"> The date fields contain non-negative integer values, constrained by the natural rules for dates using the  Common Era calendar. Please note a few things you might not think about if you are not a &#8220;data junkie&#8221; who stayed up to  watch the leap-second one night.  <\/p>\n<p class=\"MsoPlainText\"> There is no year zero. There are no negative years, either. The correct postfix is &#8220;CE&#8221;, and &#8220;BCE&#8221; for  &#8220;Common Era&#8221; and &#8220;Before Common Era&#8221; dates, replacing AD (&#8220;Anno Domini &#8216;) and BC (&#8220;Before Christ).  <\/p>\n<p class=\"MsoPlainText\"> Standard SQL also has an <code>INTERVAL  <\/code> data type. This is a &#8220;mixed measurement&#8221;, made up of temporal fields,  just as we Americans mix feet and inches. An <code>INTERVAL  <\/code> is a period of time, such as &#8220;3 years 2 months&#8221; or &#8220;90 days&#8221;; in  T-SQL we have to use a single unit of temporal measurement in a parameter in an old Sybase function call to <code>DATEADD()<\/code> ,<code> DATEDIFF()<\/code> and so forth.  <\/p>\n<p class=\"MsoPlainText\"> The reason for the Sybase model is historical. The temporal data types were not in the Standards and the  Sybase clock was based on a floating point number in the hardware. Following the UNIX model, we used clock ticks on the  old 16-bit hardware. It works well with C programs, too.  <\/p>\n<p class=\"MsoPlainText\"> There are effectively two kinds of <code>INTERVAL<\/code> sub-types for using with dates (there are more for time fields  , but I am not talking about it here).   <\/p>\n<ol>\n<li><code>YEAR<\/code> &#8211;<code>MONTH<\/code> contains one or both <code>YEAR <\/code> and <code>MONTH <\/code> fields. <\/li>\n<li>&#8220;<code>DAY<\/code> &#8221; contains a positive or negative number of days. This looks like what we do in T-SQL, but without the  \t\tmixed units and different syntax. . <\/li>\n<\/ol>\n<p class=\"MsoPlainText\"> \tThe reason for the two interval types is to avoid the ambiguity that would arise if a <code>MONTH \t <\/code> value was  combined with a field of lower significance, e.g. <code>DAY<\/code>, given that different months contain differing numbers of days.  For example, the interval &#8220;2 months and 10 days&#8221; could vary between 69 and 72 days in length, depending on the months  involved. Therefore, to avoid unwanted variations in the downstream arithmetic etc., the variable length <code>MONTH<\/code> component  may only exist at the lowest significance level in an <code>INTERVAL<\/code> . <\/p>\n<p class=\"MsoPlainText\"> The value of a <code>MONTH<\/code> field, which is not in the leading field position, is constrained between 0 and 11, in  an <code>INTERVAL<\/code> (and not between 1 and 12 as in a <code>DATE<\/code>). You have to round up a dozen months to a year, just you do not  describe yourself as &#8220;five foot, 1 fourteen inches&#8221; on an application.  <\/p>\n<p class=\"MsoPlainText\"> You can assume that your SQL implementation has simple date arithmetic functions, although with different  syntax from product to product. The basic functions you need are just those that work with dates: <\/p>\n<ul>\n<li>A date plus or minus an interval of days yields a new date. <\/li>\n<li>&#160;A date minus a second date yields an interval of days. <\/li>\n<\/ul>\n<p class=\"MsoPlainText\"> Here is a table of the valid combinations of &lt;date&gt; and &lt;interval&gt; data types in Standard SQL: <\/p>\n<table class=\"MsoNormalTable\">\n<tbody>\n<tr>\n<td colspan=\"2\" valign=\"top\">\n<p class=\"MsoPlainText\"> \t\tANSI\/ISO  \t\tStandard SQL Math  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t&lt;date&gt; &#8211; &lt;date&gt;  \t\t= &lt;interval&gt;   <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t&lt;date&gt; +  \t\t&lt;interval&gt; = &lt;date&gt;   <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t&lt;interval&gt; (*  \t\tor \/) &lt;numeric&gt; = &lt;interval&gt;   <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t&lt;interval&gt; +  \t\t&lt;date&gt; = &lt;date&gt;   <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t&lt;interval&gt; +  \t\t&lt;interval&gt; = &lt;interval&gt;   <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t&lt;numeric&gt; *  \t\t&lt;interval&gt; = &lt;interval&gt;   <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p class=\"MsoPlainText\"> There are other rules, which deal with time zones and the relative precision of the two operands that are  intuitively obvious. You can also &#8220;<code>CAST<\/code> (&lt;string expression&gt; AS <code>INTERVAL<\/code> &lt;interval type&gt;)&#8221; if you need it.   <\/p>\n<p class=\"MsoPlainText\"> There should also be a function that returns the current date from the system clock. This function has a  different name with each vendor: <code>TODAY, SYSDATE, NOW(), CURRENT DATE<\/code> and  <code>getdate() <\/code>are some examples. The correct  keyword is <code>CURRENT_TIMESTAMP<\/code> for the system timestamp and<code> CURRENT_DATE<\/code> for the system date. T-SQL now has  <code>CURRENT_TIMESTAMP<\/code> to replace the 1970&#8217;s <code>getdate() <\/code>from Sybase. Microsoft has been bad about getting up to specs, so  T-SQL will still generate the old <code>getdate()<\/code> function call. Try to avoid it so you will look like one of cool kids and  hope Microsoft keeps making progress. You can also use <code>CAST (CURRENT_TIMESTAMP AS DATE) <\/code> for  <code>CURRENT_DATE<\/code> .   <\/p>\n<h2><b> Leap Year <\/b><\/h2>\n<p class=\"MsoPlainText\">You ought to know better, but I am posting a warning anyway. You might remember being told in grade school  that there are 365 &#194;&#188;  days per year and that the accumulation of the fractional  day creates a leap year every four years. Once more, your teachers lied to you; there are really 365.2422 days per year.  Every four years, the extra 0.2400 days accumulate and create an additional day; this gives us a leap year. Every 400  years the extra 0.0022 days accumulate enough to create an additional day and give us this special leap year. Since most  of us are not over 400 years old, we did not have to worry about this until the year 2000. However, every 100 years the  missing 0.01 days (i.e. 365.25 &#8211; 365.2422 rounded up) balances out and we do not have a leap year. <\/p>\n<p class=\"MsoPlainText\"> The correct test for leap years is:  <\/p>\n<pre class=\"theme:ssms2012 lang:tsql highlight:0 decode:true\">CASE WHEN (my_year %400) = 0 THEN 'Yes' \nWHEN MOD(my_year % 100) = 0 THEN 'No' \nELSE CASE WHEN MOD(my_year % 4) = 0 \n&#160;&#160;&#160;&#160; THEN 'Yes' ELSE 'No 'END ; \n&#160; END; \n<\/pre>\n<p class=\"MsoPlainText\"> People who did not know this algorithm wrote lots of programs. I do not mean COBOL legacy programs in your  organization; I mean packaged programs for which you paid good money. The date functions in the first releases of Lotus,  Excel and Quattro Pro did not handle the day 2000-02-29 correctly. Lotus simply made an error and the others followed  suit to maintain &#8220;Lotus compatibility&#8221; in their products. Microsoft Excel for Windows Version 4 shows correctly that the  next day after 2000-02-28 is 2000-03-01. However, it thought that the next day after 1900-02-28 is also February 29  instead of March 01. Microsoft Excel for Macintosh did not handle the years 1900-1903.  <\/p>\n<p class=\"MsoPlainText\"> Do not worry about working with other products and Standard SQL. I just want to help you <i>read<\/i>  Standard SQL, but we are not done yet. The ISO-8601 Standards include an ordinal date and a week date format.   <\/p>\n<h2> <b>Daily Exercise <\/b> <\/h2>\n<p class=\"MsoPlainText\">If you do not like the way  that Pope Gregory arranged the months, do not blame him. He inherited that stuff from  the Romans. The simplest way to label the days of the year is to number the days from 1 to 365 (or 366 in a leap year)  without any further aggregations. This is called an &#8220;Ordinal date&#8221; and it is formatted as <code>\"yyyy-ddd<\/code>&#8216; where ddd is an  integer string with leading zeros between &#8216;001&#8217; to &#8216;366&#8217; when displayed. It is <i>not <\/i>called the &#8220;Julian date&#8221;,  contrary to popular belief. The Julian date is a special count of days used by astronomers based on the Julian Day  Number (JDN) (http:\/\/en.wikipedia.org\/wiki\/Julian_date). The Julian day number zero begins with 4714-11-24 BCE, it and  gets big in modern times. For example, the Julian day number for 2000-01-01 was 2,451,545.     <\/p>\n<p class=\"MsoNormal\">You probably want to use a   <i>&#8216;Julianized&#8217; date.  <\/i>This sequence starts with some date that makes sense for your  enterprise, say a century or two. Obviously this numbering will make math easier. But good trick is the   &#8216;Julianized&#8217;  business date. Instead of using a monotonic increasing sequence, use an increasing sequence (i.e. it has duplicated  values). This is easier to explain with an example. Assume it is 2007 and our company takes Easter as a long holiday  (this is a year with Catholic and Orthodox calendars agree).   <\/p>\n<pre class=\"theme:ssms2012 lang:tsql highlight:0 decode:true\">CREATE TABLE Business_Calendar \n(cal_date DATE NOT NULL PRIMARY KEY, \n&#160; julian_business_nbr INTEGER NOT NULL, \n&#160; ...); \n\nINSERT INTO Business_Calendar \nVALUES ('2007-04-05', 242), \n&#160; ('2007-04-06', 243), -- Good Friday \n&#160; ('2007-04-07', 243), \n&#160; ('2007-04-08', 243), -- Easter Sunday \n&#160; ('2007-04-09', 244), \n&#160; ('2007-04-10', 245),; --Tuesday \n&#160; .. ;  \n\n\n<\/pre>\n<p class=\"MsoNormal\">To compute the<i>  business <\/i>days from Thursday of this week to next Tuesdays:  <\/p>\n<pre class=\"theme:ssms2012 lang:tsql highlight:0 decode:true\">SELECT (C2.julian_business_nbr - C1.julian_business_nbr) \n&#160; FROM Business_Calendar AS C1, Business_Calendar AS C2 \n&#160; WHERE C1.cal_date = '2007-04-05', \n&#160;&#160; AND C2.cal_date = '2007-04-10';  \n<\/pre>\n<p class=\"MsoNormal\">Do not try to compute holidays with temporal math functions.  Look at the formula for Easter; it is mess. And <i>which<\/i> Easter did you mean? If  you are an American, do you remember all the holidays for the fifty states? When did we create President&#8217;s Day from  Washington&#8217;s and Lincoln&#8217;s Birthday?   <\/p>\n<p class=\"MsoNormal\">The <code>DATE<\/code> data type is only three bytes, and a century worth  of dates is only 36,525 rows. This is cheap and small for today&#8217;s computers. The table is read-only forever and is  indexed on the &#8220;<code>cal_date<\/code>&#8221; with other display formats as <code>INCLUDE<\/code> columns on the index. But more than that, the common  Business Calendar prevents bad data. I worked with a Greek and a Russian Orthodox programmer who had gotten their Easter  list from their priest. I had two matching answers, so I accepted the it. But other calendars in the company were done  by Catholics. You can see the problems.   <\/p>\n<h2> <b>A Week Defense <\/b><\/h2>\n<p>In most SQL products there is a vendor function to return the day of the week from a date, which is  sometimes called DOW() or WEEK<code>DAY<\/code> (). The underlying formula is called Zeller&#8217;s congruence  (http:\/\/en.wikipedia.org\/wiki\/Zeller%27s_congruence) which has versions for both the old Julian and the Common Era  calendars. This was what we used in the old days because the math was hidden in a procedure call in C. We all had a copy  of &#8220;Standard C Date\/Time Library&#8221; by Lance Latham, (ISBN : 087930-496-0 or ASIN:&#160;B00336ESWE now on Kindle).   <\/p>\n<p class=\"MsoPlainText\"> The problem is that Zeller&#8217;s formula returns a number between zero and six &#8211; it has a MOD() function in it.  Too bad this wrong. The&#160; <a href=\"http:\/\/en.wikipedia.org\/wiki\/ISO_week_date\">ISO  Standard  <\/a> Day-of-Week is defined  as 1 = Monday to 7 = Sunday. The Microsoft <code>DATE<\/code> PART() also returns a number from 1 to 7, but with the default of 1 =  Sunday to 7 = Saturday. As a generalization, ISO prefers to use zero as a value for a missing or unknown value in an  encoding scheme. I will explain why that is useful a little later in this article.   <\/p>\n<p class=\"MsoPlainText\"> The ISO-8601 Standard includes a &#8220;week date&#8221; format based on the day-within-week within year that is  popular in Nordic countries. This format is &#8216;<code>yyyyWww-d<\/code>&#8216; where <code>yyyy <\/code>is the year, W is a separator token, <code>ww<\/code> is (01-53)  week number and <code>d<\/code> is (1-7) day of the week, as we just discussed. To make this easy to validate, use:  <\/p>\n<pre class=\"theme:ssms2012 lang:tsql highlight:0 decode:true\">&#160; CHECK (week_date LIKE '[12][0-9][0-9][0-9]W[[0-5][0-9]-[1-7]' <\/pre>\n<p>Weeks start with Monday. The first week of a year is the week  that contains the first Thursday (and, hence, January 4th) of their year.  There are several websites with calendars you can cut and paste, but you can start your search with:  <a href=\"http:\/\/www.epochconverter.com\/date-and-time\/weeknumbers-by-year.php\">Week Numbers for 2014<\/a>. Now look at this year and notice that 2014W52 ends  in 2014, but 2015W01 overlaps into 2015.   <\/p>\n<table class=\"MsoNormalTable\">\n<tbody>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\tWeek  <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\tStart Date  <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\tEnd Date  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t1 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-30 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-05  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-06 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-12  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t3 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-13 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-19  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t4 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-20 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-26  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t5 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-01-27 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-02  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t6 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-03 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-09  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t7 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-10 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-16  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t8 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-17 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-23  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t9 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-02-24 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-02  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t10 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-03 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-09  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t11 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-10 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-16  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t12 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-17 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-23  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t13 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-24 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-30  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t14 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-03-31 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-06  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t15 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-07 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-13  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t16 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-14 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-20  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t17 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-21 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-27  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t18 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-04-28 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-04  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t19 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-05 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-11  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t20 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-12 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-18  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t21 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-19 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-25  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t22 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-05-26 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-01  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t23 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-02 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-08  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t24 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-09 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-15  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t25 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-16 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-22  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t26 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-23 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-29  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t27 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-06-30 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-06  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t28 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-07 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-13  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t29 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-14 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-20  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t30 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-21 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-27  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t31 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-07-28 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-03  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t32 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-04 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-10  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t33 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-11 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-17  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t34 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-18 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-24  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t35 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-25 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-08-31  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t36 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-01 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-07  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t37 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-08 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-14  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t38 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-15 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-21  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t39 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-22 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-28  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t40 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-09-29 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-05  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t41 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-06 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-12  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t42 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-13 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-19  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t43 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-20 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-26  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t44 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-10-27 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-02  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t45 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-03 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-09  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t46 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-10 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-16  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t47 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-17 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-23  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t48 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-24 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-11-30  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t49 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-01 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-07  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t50 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-08 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-14  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t51 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-15 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-21  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t52 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-22 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-29-28  <\/p>\n<\/td>\n<\/tr>\n<tr>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t1 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2014-12-29 <\/p>\n<\/td>\n<td valign=\"top\">\n<p class=\"MsoPlainText\"> \t\t2015-01-04  <\/p>\n<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h2><b>Report Period Tables <\/b> <\/h2>\n<p class=\"MsoNormal\">Since SQL is a database language, we prefer to do look-ups and not calculations. They can be optimized  while temporal math messes up optimization. A useful idiom is a report period calendar that everyone uses so there is no  way to get disagreements in the DML. The report period table gives a name to a range of dates that is common to the  entire enterprise and which applies to a particular report&#8217;s reporting periods.  <\/p>\n<pre class=\"theme:ssms2012 lang:tsql highlight:0 decode:true\">\nCREATE TABLE Something_Report_Periods \n(something_report_name CHAR(??) NOT NULL PRIMARY KEY \n&#160;&#160; CHECK (something_report_name LIKE &lt;sortable pattern&gt;), \n&#160; something_report_start_date DATE NOT NULL, \n&#160; something_report_end_date DATE NOT NULL, \n&#160; CONSTRAINT Date_Ordering \n&#160;&#160; CHECK (something_report_start_date &lt;= something_report_end_date), \netc); \n<\/pre>\n<p class=\"MsoNormal\">These report periods can overlap, have gaps or no particular pattern at all. I like the MySQL convention of  using double zeroes for whole months and years. That uses &#8216;<code>yyyy-mm-00<\/code>&#8216; for a month within a year and &#8216;<code>yyyy-00-00<\/code>&#8216; for  the whole year. The patterns for using<code> LIKE<\/code> are <code>'[12][0-9][0-9][0-9]-00-00' <\/code>and &#8216;[<code>12][0-9][0-9][0-9]-[01][0-9]-00'<\/code> in a  validation.  <\/p>\n<p class=\"MsoNormal\">The advantages are that it will sort with the ISO-8601 data format required by Standard SQL and it is  language independent. Using the<code> Date_Ordering<\/code> <code>CHECK() <\/code>constraint will help the optimizer as well as preventing  unintended time travel.  <\/p>\n<p class=\"MsoPlainText\"> Another useful trick is the ISO half-open interval model of time. Time moves in one direction, forward.,  into an unknown future. This is why an event will start before it ends and why we might not have a known ending date.   <\/p>\n<p class=\"MsoPlainText\"> Unlike the IEEE  754   Floating Point Standards, we do not have a &#8220;plus and minus eternity&#8221; to correspond to their numeric&#160;  plus and minus infinities. But we can use a <code>CAST (NULL AS DATE) <\/code>in the <code>end_date<\/code> column and a non-NULL <code>start_date<\/code>.  The trick is to remember to coalesce that NULL in queries:  <\/p>\n<pre class=\"theme:ssms2012 lang:tsql highlight:0 decode:true\">\t\tSELECT COUNT(room_nbr) AS occupancy_tot \n&#160; FROM Hotel_Rooms \n&#160; WHERE room_status = 'occupied' \n&#160;&#160; AND @my_report_date \n&#160;&#160;&#160;&#160;&#160;&#160; BETWEEN checkin_date  \n&#160;&#160;&#160;&#160;&#160;&#160; AND COALESCE (checkout_date, CURRENT_TIMESTAMP);  \n<\/pre>\n<h2><b> Reading Assignment: <\/b><\/h2>\n<p> Here are a few books for a quick reading list. <\/p>\n<ul>\n<li> \t\t<i>Humanity&#8217;s Epic Struggle to Determine a True and Accurate Calendar:  <\/i> by David Ewing Duncan; ISBN-13: 978-0380975280. <\/li>\n<li> \t\t<i>The Oxford Companion to the Year: An Exploration of Calendar Customs and Time-Reckoning <\/i> by Bonnie Blackburn; ISBN-13: 978-0192142313. <\/li>\n<li> \t\t<i>Mapping Time: The Calendar and Its History  <\/i> \t\tby E. G. Richards;  ISBN-13: 978-0192862051. <\/li>\n<li> \t\t<i>The Seven Day Circle <\/i> by E. Zerubavel; ISBN-13: 978-0029346808. This is the  detailed history of the week and other units less than a month in many calendars.\n<\/p>\n<\/li>\n<\/ul>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>The calendar is inherently complex by the very nature of the astronomy that underlies the year, and the conflicting historical conventions. The handling of dates in TSQL is even more complex because, when SQL Server was Sybase, it was forced by the lack of prevailing standards in SQL  to create its own ways of processing and formatting dates and times. Joe Celko looks forward to a future when it is possible to write standard SQL date-processing code with SQL Server.&hellip;<\/p>\n","protected":false},"author":96214,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143531],"tags":[4150,4151,4252,4190],"coauthors":[],"class_list":["post-1769","post","type-post","status-publish","format-standard","hentry","category-t-sql-programming-sql-server","tag-sql","tag-sql-server","tag-t-sql-programming","tag-tsql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1769","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/96214"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=1769"}],"version-history":[{"count":4,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1769\/revisions"}],"predecessor-version":[{"id":41008,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/1769\/revisions\/41008"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=1769"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=1769"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=1769"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=1769"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}