Date and Time
Explore MySQL's date and time data types to learn how to store and manipulate dates, times, and timestamps effectively. This lesson covers the formats, ranges, and specific use cases for DATE, TIME, DATETIME, TIMESTAMP, and YEAR data types, helping you manage temporal data in databases.
Date and time are an integral part of every database. Even if the data in a database is not related to date and time by topic, SQL tables often include columns with metadata. For example, a table may include metadata like the date and time at which a record was created:
Hence, MySQL provides various data types related to storing date and time, i.e., DATE, TIME, DATETIME, TIMESTAMP, and YEAR. With our running example of a table that stores car models, we already encountered a data type to represent years:
Beyond a car model’s release year, we could also be interested in recording metadata about the car models that our table CarModel stores. Even more so, our car models are assembled in a factory, where the engineers are interested in the state of assembly, i.e., the date and time when certain parts were assembled. Therefore, we need to look into data types that are more fine-grained than YEAR.
The DATE for dates
The data type for representing dates in MySQL is DATE. Values of this data type are represented as 'YYYY-MM-DD'. Working with a table with a column of type DATE, for example, allows us to input a value in the previously mentioned format and various others. 'YYYY-MM-DD' (also without limiters), 'YY-MM-DD' (also without delimiters), YYYYMMDD, and YYMMDD are supported for input parsing.
Previously, using delimiters other than - was permitted, but it is deprecated as of MySQL 8.0.29 and will display a warning. Regardless of the format used, the values permitted for DATEs range from 1000-01-01 to 9999-12-31. Per definition, a DATE is not associated with a particular TIME; for that we need to turn to DATETIME.
The TIME[(fsp)] for time
TIME[(fsp)] is the data type that represents time in MySQL. The format used to represent values of this type is 'hhh:mm:ss[.fraction]' where hhh represents hours, mm represents minutes, and ss represents seconds. TIME[(fsp)] not only represents the hours of the day but can also convey elapsed time and the time between two events. Hence, the hours count has not only two but three digits. [.fraction] represents the optional fractional part of a second and corresponds to a sequence of fsp (fractional seconds precision) digits where fsp can range from 0 (default) to 6. For example, '17:03:46.031' is a valid value for a row’s field with the data type TIME(3). Aside from the format mentioned above, TIME[(fsp)] can be input as 'D hh:mm:ss' (also permitted with fractional part), 'hh:mm:ss' (also permitted without delimiters and with fractional part), 'hh:mm', 'D hh:mm', 'D hh', and 'ss'. Numerically, the formats hhmmss (also permitted with a fractional part), mmss, and ss are also supported. For all these formats, the values permitted range from -838:59:59.000000 to 838:59:59.000000.
The DATETIME[(fsp)] for dates with associated time
The data type representing a date associated with a time of the day in MySQL is DATETIME[(fsp)]. It is not exactly a combination of DATE and TIME but close. The format used to represent DATETIME[(fsp)] is 'YYYY-MM-DD hh:mm:ss[.fraction]' where [.fraction] corresponds to an optional sequence of fsp digits. Hence, fsp can range from 0 (default) through 6. For example, '2022-01-01 00:00:00.01' is a valid value for a column with data type DATETIME(2). For parsing a value of type DATETIME[(fsp)], the format is identical to DATE but includes a time of the day, e.g., YYYYMMDDhhmmss (as a number) is a valid value for DATETIME[(fsp)]. In addition to the whitespace character between the date and time part, the T character is a valid separator. Using delimiters other than : for the time part was previously permitted but is deprecated as of MySQL 8.0.29 and will display a warning. Regardless of the format used, the values permitted for the time of the day range from 00:00:00 to 23:59:59. The values valid for the date part are the same as for DATE. With this knowledge, we are now able to extend our running example of car models with a record of assembled car parts:
The table CarPart consists of three columns, namely model, name, and built_at. The first column, model, references the car model that this part belongs to as a foreign key (i.e., FOREIGN KEY (model) REFERENCES CarModel (id)). name records the name of the car part and constitutes the primary key of CarPart together with model (i.e., PRIMARY KEY (model, name(256))). For our example, we consider three parts, namely exterior, interior, and wheels. Finally, the third column, built_at, contains the date and time the corresponding part has been assembled. If that hasn’t happened so far for a part, the column reads NULL. As such, we can record car models and their parts as such:
Notably, we can specify the assembly date and time as discussed in this section.
The TIMESTAMP[(fsp)] for dates with associated time
Similar to DATETIME[(fsp)], TIMESTAMP[(fsp)] is the data type in MySQL to represent a date associated with a time of the day. However, TIMESTAMP[(fsp)] has a more constrained range and stores time with time zone information. The formats used to represent and parse TIMESTAMP[(fsp)] are identical to DATETIME[(fsp)]. However, storing a value of type TIMESTAMP[(fsp)] causes the value to be converted from the server’s (where MySQL is running) time zone to UTC. Similarly, retrieving a value of type TIMESTAMP[(fsp)] causes the value to be converted from UTC to the server’s time zone. As mentioned, the TIMESTAMP[(fsp)] range is constrained from 1970-01-01 00:00:01 UTC to 2038-01-19 03:14:07 UTC.
The YEAR for years
As discussed in the beginning, MySQL provides the data type YEAR with the display format YYYY to represent a single year. For input parsing of YEAR, 'YYYY', 'YY', and 'Y' are equally valid. In the case of the latter two shortcut formats, the strings '0' through '69' are associated with the years 2000 to 2069, while the strings '70' through '99' are associated with the years 1970 to 1999. Numerically, the same data formats are accepted. In this case, the values from 1 through 69 are associated with the years 2001 to 2069, while the values from 70 to 99 are associated with the years 1970 to 1999. A numerical value 0 is associated with the year 0000. In all cases, the values permitted for YEAR include 0000 and years from 1901 through 2155.
Automatic initialization of date and time
For DATETIME and TIMESTAMP, we can use DEFAULT CURRENT_TIMESTAMP (or alternatives to CURRENT_TIMESTAMP, like NOW() or LOCALTIME) to automatically initialize the corresponding column in the row to the current time:
The same is possible for ON UPDATE, setting the corresponding column in the row to the current time as soon as another field is updated.