Hour 16

Understanding Dates and Times

What You’ll Learn in This Hour:

In this hour, you learn about the nature of dates and times in SQL. Not only does this hour discuss the DATETIME data type in more detail, but you also see how some implementations use dates, learn how to extract the date and time in your desired format, and familiarize yourself with some of the common rules.

Note

Variations in the SQL Syntax

As you know by now, many different SQL implementations exist. This book follows the American National Standards Institute (ANSI) standard and illustrates the most common nonstandard functions, commands, and operators. Oracle is used for the examples. Even in Oracle, however, the date can be stored in different formats, so check your particular implementation for details. No matter how it is stored, your implementation should have functions that convert date formats.

Understanding How a Date Is Stored

Each implementation has a default storage format for the date and time. This default storage often varies among different implementations, as do other data types for each implementation. The following sections begin by reviewing the standard format of the DATETIME data type and its elements. Then you see the data types for date and time in some popular implementations of SQL, including Oracle, MySQL, and Microsoft SQL Server.

Standard Data Types for the Date and Time

Three standard SQL data types are used for date and time (DATETIME) storage. In a relational database, the date can be stored and retrieved as a basic date format, or can include a time of day, or can include a time stamp based on certain intervals (according to the options available in each SQL implementation):

  •    DATE—Stores date literals. DATE is formatted as YYYY-MM-DD and ranges from 0001-01-01 to 9999-12-31.

  •    TIME—Stores time literals. TIME is formatted as HH:MI:SS.nn... and ranges from 00:00:00... to 23:59:61.999....

  •    TIMESTAMP—Stores date and time literals. TIMESTAMP is formatted as YYYY-MM-DD HH:MI:SS.nn... and ranges from 0001-01-01 00:00:00... to 9999-12-31 23:59:61.999....

DATETIME Elements

DATETIME elements pertain to the date and time and are included as part of a DATETIME definition. The following is a list of the constrained DATETIME elements and a valid range of values for each element.

DATETIME Element

Valid Ranges

YEAR

0001 to 9999

MONTH

01 to 12

DAY

01 to 31

HOUR

00 to 23

MINUTE

00 to 59

SECOND

00.000... to 61.999...

Each of these is an element of time that you deal with on a daily basis. Seconds can be represented as a decimal, enabling you to express tenths of a second, hundredths of a second, milliseconds, and so on. According to the ANSI standard, a minute is defined as 61.999 seconds, due to the possible insertion or omission of a leap second in a minute, which is a rare occurrence. Refer to your implementation on the allowed values; date and time storage can vary widely.

Tip

Databases Handle Leap Years

Date variances, such as leap seconds and leap years, are handled internally by the database if the data is stored in a DATETIME data type.

Implementation-Specific Data Types

As with other data types, each implementation provides its own representation and syntax. Table 16.1 shows how three products (Microsoft SQL Server, MySQL, and Oracle) have been implemented with a date and time.

TABLE 16.1 DATETIME Types Across Platforms

Product

Data Type

Use

Oracle

DATE

Stores both date and time information

SQL Server

DATETIME

Stores both date and time information

SMALLDATETIME

Same as DATETIME, except that it has a small range

DATE

Stores a date value

TIME

Stores a time value

MySQL

DATETIME

Stores both date and time information

TIMESTAMP

Stores both date and time information

DATE

Stores a date value

TIME

Stores a time value

YEAR

1-byte type that represents the year

Tip

Even Date and Time Types Can Differ

Each implementation has its own specific data type(s) for date and time information. However, most implementations comply with the ANSI standard; all elements of the date and time are included in their associated data types. The way the date is internally stored is implementation dependent.

Using Date Functions

Date functions are available in SQL, depending on the options with each specific implementation. Date functions, similar to character string functions, manipulate the representation of date and time data. Available date functions are often used to format the output of dates and time in an appealing format, compare date values with one another, compute intervals between dates, and so on.

Retrieving the Current Date

The current date is normally returned either to compare it to a stored date or to return the value of the current date as some sort of time stamp. The current date is ultimately stored on the host computer for the database and is called the system date. The database, which interfaces with the appropriate operating system, has the capability to retrieve the system date for its own purpose or to resolve database requests, such as queries.

Take a look at a couple methods of attaining the system date, based on commands from two different implementations.

Microsoft SQL Server uses a function called GETDATE() to return the system date. This function is used in a query as follows:

SELECT GETDATE()
2015-06-01 19:23:38.167

MySQL uses the NOW function to retrieve the current date and time. NOW is called a pseudocolumn because it acts as any other column in a table and can be selected from any table in the database; however, it is not actually part of the table’s definition.

The following MySQL statement returns the output if today were June 1, 2015:

SELECT NOW ();
01-JUN-15 13:41:45

Oracle uses a function known as SYSDATE and looks like this if using the DUAL table, which is a dummy table in Oracle:

SELECT SYSDATE FROM DUAL;
01-JUN-15 13:41:45

The default date format is typically set by the database administrator upon database creation. Oracle’s default date normally includes a 2-digit year. The following command used at the Oracle SQL prompt changes the date format for the current session for the sample database so that it includes the full 4-digit year, to avoid any confusion.

SQL> alter session set NLS_DATE_FORMAT='mm-dd-yyyy';

Session altered.

Because no date columns are stored in the current BIRDS database, the following PHOTOGRAPHERS table was created to include the photographer’s date of birth and the date that a given photographer started photography. In Oracle, the datatype for a date is simply DATE. The PHOTOGRAPHERS table also has records inserted to include the two new date fields.

SQL> drop table photographers;

Table dropped.

SQL> create table photographers
  2  (p_id            number(3)     not null     primary key,
  3   photographer    varchar(30)   not null,
  4   mentor_p_id     number(3)     null,
  5   dob             date          not null,
  6   dt_start_photo  date          not null,
  7   constraint p_fk1 foreign key (mentor_p_id) references photographers (p_id));

Table created.


SQL> insert into photographers values ( 7, 'Ryan Notstephens' , null, '07-16-1975',
'07-16-1989');

1 row created.

SQL> insert into photographers values ( 8, 'Susan Willamson' , null, '12-03-1979',
'02-22-2016');

1 row created.

SQL> insert into photographers values ( 9, 'Mark Fife' , null, '01-31-1982',
'12-25-2000');

1 row created.

SQL> insert into photographers values ( 1, 'Shooter McGavin' , null, '02-24-2005',
'01-01-2019');

1 row created.

SQL> insert into photographers values ( 2, 'Jenny Forest' , 8, '08-15-1963',
'08-16-1983');

1 row created.

SQL> insert into photographers values ( 3, 'Steve Hamm' , null, '09-14-1969',
'01-01-2000');

1 row created.

SQL> insert into photographers values ( 4, 'Harry Henderson' , 9, '03-22-1985',
'05-16-2011');

1 row created.

SQL> insert into photographers values ( 5, 'Kelly Hairtrigger' , 8, '01-25-2001',
'02-01-2019');

1 row created.

SQL> insert into photographers values ( 6, 'Gordon Flash' , null, '09-14-1971',
'10-10-2010');

1 row created.

SQL> insert into photographers values ( 10, 'Kate Kapteur' , 7, '09-14-1969',
'11-07-1976');

1 row created.

SQL> commit;

Commit complete.

The current date is ultimately stored on the host computer for the database and is called the system date. The following query returns the system date from the DUAL table. As mentioned previously, this is a dummy table in Oracle from which any literal string can be submitted.

SQL> select sysdate from dual;

SYSDATE
----------
07-24-2021

1 row selected.

In the next example, you select the system date from every row of data in the PHOTOGRAPHERS table. This might not seem desirable, but it offers an illustration of how the system date can be compared to any value that is stored in a database column, just like any literal string.

SQL> select sysdate from photographers;

SYSDATE
----------
07-24-2021
07-24-2021
07-24-2021
07-24-2021
07-24-2021
07-24-2021
07-24-2021
07-24-2021
07-24-2021
07-24-2021

10 rows selected.

In practical use, you might use the system date to compare photographers’ dates of birth or dates photographers started taking photos as a hobby or career.

Dealing with Time Zones

Time zones can be a factor when dealing with date and time information. For instance, a time of 6:00 p.m. in the central United States does not equate to the same time in Australia, although the actual point in time is the same. People who live within the daylight savings time zone are accustomed to adjusting their clocks twice a year. If time zones are considerations when maintaining data in your case, you might need to consider time zones and perform time conversions, if they are available with your SQL implementation.

The following table lists some common time zones and their abbreviations.

Abbreviation

Time Zone

AST, ADT

Atlantic Standard Time, Atlantic Daylight Time

BST, BDT

Bering Standard Time, Bering Daylight Time

CST, CDT

Central Standard Time, Central Daylight Time

EST, EDT

Eastern Standard Time, Eastern Daylight Time

GMT

Greenwich Mean Time

HST, HDT

Alaska/Hawaii Standard Time, Alaska/Hawaii Daylight Time

MST, MDT

Mountain Standard Time, Mountain Daylight Time

NST

Newfoundland Standard Time, Newfoundland Daylight Time

PST, PDT

Pacific Standard Time, Pacific Daylight Time

YST, YDT

Yukon Standard Time, Yukon Daylight Time

The following table shows examples of time zone differences based on a given time.

Time Zone

Time

AST

June 12, 2015, at 1:15 p.m.

BST

June 12, 2015, at 6:15 a.m.

CST

June 12, 2015, at 11:15 a.m.

EST

June 12, 2015, at 12:15 p.m.

GMT

June 12, 2015, at 5:15 p.m.

HST

June 12, 2015, at 7:15 a.m.

MST

June 12, 2015, at 10:15 a.m.

NST

June 12, 2015, at 1:45 p.m.

PST

June 12, 2015, at 9:15 a.m.

YST

June 12, 2015, at 8:15 a.m.

Note

Handling Time Zones

Some implementations have functions that enable you to deal with different time zones. However, not all implementations support the use of time zones. Be sure to verify the use of time zones in your particular implementation, as well as your database’s need to deal with them.

Adding Time to Dates

You can add days, months, and other components of time to dates so that you can compare them or provide more specific conditions in the WHERE clause of a query.

The following example is a query from the PHOTOGRAPHERS table that shows the photographer’s name and date of birth.

SQL> select photographer, dob
  2  from photographers;

PHOTOGRAPHER                   DOB
------------------------------ ----------
Ryan Notstephens               07-16-1975
Susan Willamson                12-03-1979
Mark Fife                      01-31-1982
Shooter McGavin                02-24-2005
Jenny Forest                   08-15-1963
Steve Hamm                     09-14-1969
Harry Henderson                03-22-1985
Kelly Hairtrigger              01-25-2001
Gordon Flash                   09-14-1971
Kate Kapteur                   09-14-1969

10 rows selected.

Now that you have a visual of the data stored in the PHOTOGRAPHERS table for the date of birth, you can perform the following query, which uses the Oracle ADD_MONTH function to add 12 months, or 1 year, to the photographer’s date of birth. Remember that every implementation of SQL can have functions that vary in syntax, but conceptually, they are all similar as related to the SQL standard.

SQL> select photographer, dob, add_months(dob, 12) "FIRST BIRTHDAY"
  2  from photographers;

PHOTOGRAPHER                   DOB        FIRST BIRT
------------------------------ ---------- ----------
Ryan Notstephens               07-16-1975 07-16-1976
Susan Willamson                12-03-1979 12-03-1980
Mark Fife                      01-31-1982 01-31-1983
Shooter McGavin                02-24-2005 02-24-2006
Jenny Forest                   08-15-1963 08-15-1964
Steve Hamm                     09-14-1969 09-14-1970
Harry Henderson                03-22-1985 03-22-1986
Kelly Hairtrigger              01-25-2001 01-25-2002
Gordon Flash                   09-14-1971 09-14-1972
Kate Kapteur                   09-14-1969 09-14-1970

10 rows selected.

The following query is essentially the same as a previous query, except that you add 365 days instead of 12 months to the date of birth. Compare the results to the previous query.

SQL> select photographer, dob, dob + 365 "FIRST BIRTHDAY"
  2  from photographers;

PHOTOGRAPHER                   DOB        FIRST BIRT
------------------------------ ---------- ----------
Ryan Notstephens               07-16-1975 07-15-1976
Susan Willamson                12-03-1979 12-02-1980
Mark Fife                      01-31-1982 01-31-1983
Shooter McGavin                02-24-2005 02-24-2006
Jenny Forest                   08-15-1963 08-14-1964
Steve Hamm                     09-14-1969 09-14-1970
Harry Henderson                03-22-1985 03-22-1986
Kelly Hairtrigger              01-25-2001 01-25-2002
Gordon Flash                   09-14-1971 09-13-1972
Kate Kapteur                   09-14-1969 09-14-1970

10 rows selected.

Note

Variations Between Implementations

Remember that the date, formatting, and functions can vary among implementations. Although different RDBMS implementations might differ syntactically from the exact ANSI standard, they derive their results based on the same concept described by the SQL standard.

Subtracting Time

Not only can you add time to a date, but you also can subtract time and incorporate other arithmetic into your query using date values.

The following example selects the photographer’s name and the date of birth, but it subtracts the date of birth from the system date (which is today’s date) and divides the entire calculation by 365 days per year. This simple calculation derives the age of each photographer.

SQL> select photographer, (sysdate - dob)/365 "AGE"
  2  from photographers;

PHOTOGRAPHER                          AGE
------------------------------ ----------
Ryan Notstephens               46.0561876
Susan Willamson                41.6698863
Mark Fife                      39.5055027
Shooter McGavin                16.4233109
Jenny Forest                    57.982215
Steve Hamm                     51.8945438
Harry Henderson                36.3657767
Kelly Hairtrigger              20.5082424
Gordon Flash                   49.8945438
Kate Kapteur                   51.8945438

10 rows selected.

In the previous query, notice that each photographer’s age is expressed as a decimal. Of course, most people do not talk about age in decimal format. In this example, therefore, the date calculation is embedded within the ROUND function to round the age up or down accordingly. This is an example of combining arithmetic and other functions with date values to get the data that you need out of the database.

SQL> select photographer, round((sysdate - dob)/365) "AGE"
  2  from photographers;

PHOTOGRAPHER                          AGE
------------------------------ ----------
Ryan Notstephens                       46
Susan Willamson                        42
Mark Fife                              40
Shooter McGavin                        16
Jenny Forest                           58
Steve Hamm                             52
Harry Henderson                        36
Kelly Hairtrigger                      21
Gordon Flash                           50
Kate Kapteur                           52

10 rows selected.

In the following example, you want to create a query that shows the number of years of experience that Gordon Flash has. You thus eliminate all other records in the table using the WHERE clause, and instead of using the DOB column as in the previous examples, you subtract the date that Gordon started taking photos from the system date and divide by 365 days. This shows that Gordon Flash has approximately 11 years of experience in photography.

SQL> select photographer, round((sysdate - dt_start_photo)/365) "YEARS EXPERIENCE"
  2  from photographers
  3  where photographer = 'Gordon Flash';

PHOTOGRAPHER                   YEARS EXPERIENCE
------------------------------ ----------------
Gordon Flash                                 11

1 row selected.

Using Miscellaneous Date Functions

Table 16.2 shows some powerful date functions that are available in the implementations for SQL Server, Oracle, and MySQL.

TABLE 16.2 Date Functions, by Platform

Product

Date Function

Use

SQL Server

DATEPART

Returns the integer value of a DATEPART for a date

DATENAME

Returns the text value of a DATEPART for a date

GETDATE()

Returns the system date

DATEDIFF

Returns the difference between two dates for specified date parts, such as days, minutes, and seconds

Oracle

NEXT_DAY

Returns the next day of the week as specified (for example, FRIDAY) since a given date

MONTHS_BETWEEN

Returns the number of months between two given dates

MySQL

DAYNAME(date)

Displays the day of the week

DAYOFMONTH(date)

Displays the day of the month

DAYOFWEEK(date)

Displays the day of the week

DAYOFYEAR(date)

Displays the day of the year

Converting Dates

You might need to convert dates for a variety of reasons. Conversions are mainly done to alter the data type of values defined as a DATETIME value or any other valid data type of a particular implementation.

Typical reasons for date conversions are as follows:

  •    To compare date values of different data types

  •    To format a date value as a character string

  •    To convert a character string into a date format

The ANSI CAST operator converts data types into other data types. The basic syntax follows:

CAST ( EXPRESSION AS NEW_DATA_TYPE )

The following subsections illustrate specific syntax examples of some implementations and cover these tasks:

  •    Representing the parts of a DATETIME value

  •    Converting dates to character strings

  •    Converting character strings to dates

Using Date Pictures

A date picture consists of formatting elements used to extract date and time information from the database in a desired format. Date pictures might not be available in all SQL implementations.

Without the use of a date picture and some type of conversion function, the date and time information is retrieved from the database in a default format, such as the following:

2010-12-31
31-DEC-10
2010-12-31 23:59:01.11
...

Let’s say you want the date to display like this:

December 31, 2010

You now have to convert the date from a DATETIME format into a character string format. You do so using implementation-specific functions for this purpose, as you see in the following sections.

Table 16.3 displays some of the common date parts used in various implementations. This helps you use the date picture in the following sections to extract the proper DATETIME information from the database.

TABLE 16.3 Date Parts, by SQL Implementation

Product

Syntax

Date Part

SQL Server

yy

Year

qq

Quarter

mm

Month

dy

Day of the year

wk

Week

dw

Weekday

hh

Hour

mi

Minute

ss

Second

ms

Millisecond

Oracle

AD

Anno Domini

AM

Ante meridian

BC

Before Christ

CC

Century

D

Number of the day in the week

DD

Number of the day in the month

DDD

Number of the day in the year

DAY

The day spelled out (MONDAY)

Day

The day spelled out (Monday)

day

The day spelled out (monday)

DY

The three-letter abbreviation of the day (MON)

Dy

The three-letter abbreviation of the day (Mon)

dy

The three-letter abbreviation of the day (mon)

HH

Hour of the day

HH12

Hour of the day

HH24

Hour of the day for a 24-hour clock

J

Julian days since 12-31-4713 B.C.

MI

Minute of the hour

MM

The number of the month

MON

The three-letter abbreviation of the month (JAN)

Mon

The three-letter abbreviation of the month (Jan)

mon

The three-letter abbreviation of the month (jan)

MONTH

The month spelled out (JANUARY)

Month

The month spelled out (January)

month

The month spelled out (january)

PM

Post meridian

Q

The number of the quarter

RM

The Roman numeral for the month

RR

The two digits of the year

SS

The second of a minute

SSSSS

The seconds since midnight

SYYYY

The signed year; if B.C. 500, B.C. = –500

W

The number of the week in a month

Oracle

WW

The number of the week in a year

Y

The last digit of the year

YY

The last two digits of the year

YYY

The last three digits of the year

YYYY

The year

YEAR

The year spelled out (TWO-THOUSAND-TEN)

Year

The year spelled out (Two-Thousand-Ten)

year

The year spelled out (two-thousand-ten)

MySQL

SECOND

Seconds

MINUTE

Minutes

HOUR

Hours

DAY

Days

MONTH

Months

YEAR

Years

MINUTE_SECOND

Minutes and seconds

HOUR_MINUTE

Hours and minutes

DAY_HOUR

Days and hours

YEAR_MONTH

Years and months

HOUR_SECOND

Hours, minutes, and seconds

DAY_MINUTE

Days and minutes

DAY_SECOND

Days and seconds

Note

Date Parts in Oracle

This section uses some of the most common date parts for Oracle. Other date parts might be available, depending on the version of Oracle.

Converting Dates to Character Strings

DATETIME values are converted to character strings to alter the appearance of output from a query. A conversion function achieves this. Two examples of converting date and time data into a character string as designated by a query follow.

SQL implementations provide a variety of formats for displaying a date value. In this next example, you select DOB for photographers and also perform a character conversion on the default date format that is stored in the database, to produce output that might be more readable or desirable for a given situation. Take a minute to study the results.

SQL> select photographer, dob, to_char(dob, 'Day Month dd, yyyy') "LONG DOB"
  2  from photographers;

PHOTOGRAPHER          DOB        LONG DOB
--------------------- ---------- ------------------------------
Ryan Notstephens      07-16-1975 Wednesday July      16, 1975
Susan Willamson       12-03-1979 Monday    December  03, 1979
Mark Fife             01-31-1982 Sunday    January   31, 1982
Shooter McGavin       02-24-2005 Thursday  February  24, 2005
Jenny Forest          08-15-1963 Thursday  August    15, 1963
Steve Hamm            09-14-1969 Sunday    September 14, 1969
Harry Henderson       03-22-1985 Friday    March     22, 1985
Kelly Hairtrigger     01-25-2001 Thursday  January   25, 2001
Gordon Flash          09-14-1971 Tuesday   September 14, 1971
Kate Kapteur          09-14-1969 Sunday    September 14, 1969

10 rows selected.

Converting Character Strings to Dates

You can also convert character strings to dates. The following query shows an example of converting a character string using the TO_DATE function into a date value based on a literal string that you provide in the query. You can see in the results that an error was returned because of a built-in constraint within the database. The day of the week that you provided conflicts with the actual day of the week for that date in time, which the database “knows.”

SQL> select to_date('Tuesday January 6, 1999',
  2  'Day Month dd, yyyy') "New Date"
  3  from dual;
select to_date('Tuesday January 6, 1999',
               *
ERROR at line 1:
ORA-01835: day of week conflicts with Julian date

In this final example, the two DATE functions successfully convert a literal string into a date value.

SQL> select to_date('Sunday September 14, 1969',
  2  Day Month dd, yyyy') "New Date"
  3  from dual;

New Date
----------
09-14-1969

1 row selected.

Summary

You now should have an understanding of DATETIME values. ANSI provided a standard; however, as with many SQL elements, most implementations have deviated from the exact functions and syntax of standard SQL commands. Still, the concepts remain the same in terms of the basic representation and manipulation of date and time information. In Hour 15, “Restructuring the Appearance of Data,” you saw that functions vary depending on each implementation. This hour, you saw some of the differences between date and time data types, functions, and operators. Keep in mind that not all examples discussed in this hour work with your particular implementation, but the concepts of dates and times are the same and should be applicable to any implementation.

Q&A

Q. Why do implementations choose to deviate from a single standard set of data types and functions?

A. Implementations differ in their representation of data types and functions mainly because of the way each vendor chooses to internally store data and provide the most efficient means of data retrieval. However, all implementations should provide the same means for storing date and time values based on the required elements prescribed by ANSI, such as the year, month, day, hour, minute, second, and so on.

Q. What if I want to store date and time information differently than what my implementation offers?

A. Dates can be stored in nearly any type of format if you choose to define the column for a date as a variable-length character. The main point to remember when comparing date values to one another is that you are usually required to first convert the character string representation of the date to a valid DATETIME format for your implementation—that is, if appropriate conversion functions are available.

Workshop

The following workshop consists of a series of quiz questions and practical exercises. The quiz questions are designed to test your overall understanding of the current material. The practical exercises give you the opportunity to apply the concepts discussed during the current hour, as well as build on the knowledge you acquired in previous hours of study. Be sure to complete the quiz questions and exercises before continuing to the next hour. Refer to Appendix C, “Answers to Quizzes and Exercises,” for answers.

Quiz

  1. 1. Where are the system date and time normally derived from?

  2. 2. What are the standard internal elements of a DATETIME value?

  3. 3. What is a major factor for international organizations when representing and comparing date and time values?

  4. 4. Can a character string date value be compared to a date value defined as a valid DATETIME data type?

  5. 5. What do you use in SQL Server and Oracle to get the current date and time?

Exercises

  1. 1. Type the following SQL code into the sql prompt to display the current date from the database:

    SELECT SYSDATE FROM DUAL;
  2. 2. Create the PHOTOGRAPHERS table and insert the data shown at the beginning of this hour for these exercises.

  3. 3. Write a query to display all the data in the PHOTOGRAPHERS table that you just created.

  4. 4. Calculate your own age in a query using the system date.

  5. 5. Display the day of the week only that each photographer was born.

  6. 6. What is the age of Harry Henderson (rounded, of course, unless you just need to know)?

  7. 7. Which photographer has been taking photos the longest?

  8. 8. Were any photographers born on the same day?

  9. 9. Which photographers might have started taking photos because of a New Year’s resolution?

  10. 10. Write a query to determine today’s Julian date (day of year).

  11. 11. What is the combined age of all the photographers in the database?

  12. 12. Which photographer started taking photos at the youngest age?

  13. 13. Have some fun and come up with some queries of your own on this database or simply using the system date.