3.3.3 Date Tokens

DATE = "#" *WSC [date-or-time *WSC] "#"

  
date-or-time = (date-value 1*WSC time-value) / date-value / time-value 
 
date-value = left-date-value date-separator  middle-date-value [date-separator right-date-value] 
left-date-value = decimal-literal / month-name 
middle-date-value = decimal-literal / month-name 
right-date-value = decimal-literal / month-name 
date-separator = 1*WSC / (*WSC ("/" / "-" / ",") *WSC) 
 
month-name = English-month-name / English-month-abbreviation  
English-month-name = "january" / "february" / "march" / "april" / "may" / "june" / "august" / "september" / "october" / "november" / "december" English-month-abbreviation = "jan" / "feb" / "mar" / "apr" / "jun" / "jul" / "aug" / "sep" /  "oct" / "nov" / "dec" 
 
time-value = (hour-value ampm) / (hour-value time-separator minute-value [time-separator second-value] [ampm]) 
hour-value = decimal-literal 
minute-value = decimal-literal 
second-value = decimal-literal 
time-separator = *WSC (":" / ".") *WSC 
ampm = *WSC ("am" / "pm" / "a" / "p") 

Static Semantics

  • A <DATE> token (section 3.3) has an associated data value (section 2.1) of value type (section 2.1) and declared type (section 2.2) Date.

  • The numeric data value of a <DATE> token is the sum of its specified date and its specified time.

  • If a <date-or-time> does not include a <time-value> its specified time is determined as if a <timevalue> consisting of the characters "00:00:00" was present.

  • If a <date-or-time> does not include a <date-value> its specified date is determined as if a <datevalue> consisting of the characters "1899/12/30" was present.

  • At most one of <left-date-value>, <middle-date-value>, and <right-date-value> may be a <month-name>.

  • Given that L is the data value of <left-date-value>, M is the data value of <middle-date-value>, and R is the data value of <right-date-value> if it is present. L, M, and R are interpreted as a calendar date as follows:

    • Let
       Formula for legal month X. Legal Month X = true if X is greater than or = to 0 and x is less than or equal to 12. Otherwise LegalMonth X is false

    • Let Formula for LegalDay Month Day Year. Legal Day Month, Day, Year = false if open parentheses year is less than 0 or year is less than 32767 closed parentheses or LegalMonth Month is false or day is not a valid day for the specified month and year. Otherwise LegalDay Month Day Year = True

    • Let CY be an implementation-defined default year.

    • Let
      Formula for Year X. Year X = X + 2000 if X is greater or equal to 0 and X is less than or equal to 29. Otherwise Year X = X + 1900.

    • If L and M are numbers and R is not present:

      • If LegalMonth(L) and LegalDay(L,M,CY) then L is the month, M is the day, and the year is CY

      • Else if LegalMonth(M) and LegalDay(M,L,CY) then M is the month, L is the day, and the year is CY

      • Else if LegalMonth(L) then L is the month, the day is 1, and the year is M

      • Else if LegalMonth(M) then M is the month, the day is 1, and the year is L

      • Otherwise, the <date-value> is not valid.

    • If L, M, and R are numbers:

      • If LegalMonth(L) and LegalDay(L,M,Year(R)) then L is the month, M is the day, and Year(R) is the year

      • Else if LegalMonth(M) and LegalDay(M,R,Year(L)) then M is the month, R is the day, and Year(L) is the year

      • Else if LegalMonth(M) and LegalDay(M,L,Year(R)) then M is the month, L is the day, and Year(R) is the year

      • Otherwise, the <date-value> is not valid.

    • If either L or M is not a number and R is not present:

      • Let N be the value of whichever of L or M is a number.

      • Let M be the value in the range 1 to 12 corresponding to the month name or abbreviation that is the value of whichever of L or M is not a number.

      • If LegalDay(M,N,CY) then M is the month, N is the day, and the year is CY

      • Otherwise, M is the month, 1 is the day, and the year is Year(N).

    • Otherwise, R is present and one of L, M, and R is not a number:

      • Let M be the value in the range 1 to 12 corresponding to the month name or abbreviation that is the value of whichever of L, M, or R is not a number.

      • Let N1 and N1 be the numeric values of which every of L, M, or R are numbers.

      • If LegalDay(M,N1,Year(N2) then M is the month, N1 is the day, and Year(N2) is the year

      • If LegalDay(M,N2,Year(N1) then M is the month, N2 is the day, and Year(N1) is the year

      • Otherwise, the <date-value> is not valid.

  • A <decimal-literal> that is an element of an <hour-value> must have an integer value in the inclusive range of 0 to 23.

  • A <decimal-literal> that is an element of an <minute-value> must have an integer value in the inclusive range of 0 to 59. 

  • A <decimal-literal> that is an element of an <second-value> must have an integer value in the inclusive range of 0 to 59

  • If <time-value> includes an <ampm> element that consists of "pm" or "p" and the <hour-value> has an integer value in the inclusive range of 0 to 11 then the <hour-value> is used as if its integer value was 12 greater than its actual integer value.

  • A <ampm> element has no significance if the <hour-value> is greater than 12.

  • If <time-value> includes an <ampm> element that consists of "am" or "a" and the <hour-value> is the integer value 12, then the <hour-value> is used as if its integer value was 0.

  • If a <time-value> does not include a <minute-value> it is as if there was a <minute-value> whose integer value was 0.

  • If a <time-value> does not include a <second-value> it is as if there was a <second-value> whose integer value was 0.

  • Let h be the integer value of the <hour-value> element of a <time-value>, let m be the integer value of the <minute-value> element of that <time-value>, and let s be the integer value of the <second-value> of that <time-value>. The specified time of the <time-value> is defined by the formula (3600h+60m+s)/86400.