Tải bản đầy đủ - 0 (trang)
Chapter 5. Working with Dates and Times

Chapter 5. Working with Dates and Times

Tải bản đầy đủ - 0trang

Section 5.23. Finding the Length of a Month

Section 5.24. Calculating One Date from Another by Substring Replacement

Section 5.25. Finding the Day of the Week for a Date

Section 5.26. Finding Dates for Days of the Current Week

Section 5.27. Finding Dates for Weekdays of Other Weeks

Section 5.28. Performing Leap Year Calculations

Section 5.29. Treating Dates or Times as Numbers

Section 5.30. Forcing MySQL to Treat Strings as Temporal Values

Section 5.31. Selecting Records Based on Their Temporal Characteristics

Section 5.32. Using TIMESTAMP Values

Section 5.33. Recording a Row's Last Modification Time

Section 5.34. Recording a Row's Creation Time

Section 5.35. Performing Calculations with TIMESTAMP Values

Section 5.36. Displaying TIMESTAMP Values in Readable Form



5.1 Introduction

MySQL has several data types for representing dates and times, and several functions for

operating on them. MySQL stores dates and times in specific formats. It's important to

understand them to avoid surprises in how MySQL interprets input data. MySQL also has

reformatting functions for producing date and time output in formats other than the default.

This chapter covers the following aspects of working with temporal values in MySQL:







Displaying dates and times.

MySQL displays temporal values using specific formats by default, but you can produce

other formats by calling the appropriate function.







Determining the current date or time.

MySQL provides functions that return the date and time, which is useful for

applications that need to know these values or need to calculate other temporal values

in relation to them.







Decomposing dates or times into component values.

This section explains how to split date and time values when you need only a piece,

such as the month part or the hour part.







Synthesizing dates and times from component values.

The complement of splitting apart temporal values is to create them from subparts.

This section shows how.







Converting between dates or times and basic units.

Some date calculations are more easily performed using the number of days or

seconds represented by a date or time value than by using the value itself. MySQL

makes it possible to perform several kinds of conversions between date and time

values and more basic units such as days or seconds. These conversions often are

useful for interval calculations (such as time elapsed between two times).







Date and time arithmetic.

It's possible in MySQL to add temporal intervals to date or time values to produce

other dates or times, and to calculate the interval between dates or times. Time

arithmetic is easier than date arithmetic. Times involve hours, minutes, and seconds—

units that always have a fixed duration. Date arithmetic can be trickier because units

such as months and years vary in length.







Applications for date and time arithmetic.

Using the techniques from the earlier sections, this one shows how to perform age

calculation, relative date computation, date shifting, and leap year calculation.







Selecting records based on temporal constraints.

The calculations discussed in the preceding sections to produce output values can also

be used in WHERE clauses to specify how to select records using temporal conditions.







Using TIMESTAMP values.

The TIMESTAMP column type has some special properties that make it convenient for

automatically recording record creation and modification times. This section describes

how TIMESTAMP columns behave and how to use them. It also discusses how to

display TIMESTAMP values in more readable formats.



This chapter covers many of MySQL's functions for operating on date and time values, but

there are yet others. To familiarize yourself with the full set, consult the MySQL Reference

Manual. The variety of functions available to you means that it's often possible to perform a

given temporal calculation more than one way. I sometimes illustrate alternative methods for

achieving a given result, but many of the problems addressed in this chapter can be solved in

other ways than are shown here. I invite you to experiment to find other solutions. You may

find a method that's more efficient or that you find more readable.

Scripts that implement the recipes discussed in this chapter can be found in the dates

directory of the recipes source distribution. The scripts that create the tables used here are

located in the tables directory.



5.1.1 MySQL's Date and Time Formats

MySQL provides DATE and TIME column types for representing date and time values

separately, and a DATETIME type for combined date-and-time values. These values have the

following formats:







DATE values are handled as strings in CCYY-MM-DD format, where CC, YY, MM, and DD

represent the century, year within century, month, and day parts of the date.







TIME values are represented as strings in hh:mm:ss format, where hh, mm, and ss

are the hours, minutes, and seconds parts of the time. TIME values often can be

thought of as time-of-day values, but MySQL actually treats them as elapsed time.

Thus, they may be greater than 23:59:59 or even negative. (The actual range is -



838:59:59 to 838:59:59.)





DATETIME values are represented as combined date-and-time strings in CCYY-MM-DD

hh:mm:ss format.







TIMESTAMP values also include date and time parts, but are represented as strings in

CCYYMMDDhhmmss format. This column type also has special properties that are

discussed further in Recipe 5.32. More examples in this chapter use DATETIME values

than TIMESTAMP values (which are less readable), but in most respects, you can treat

the two column types the same way.



Many of the examples in this chapter draw on the following tables, which contain columns

representing TIME, DATE, DATETIME, and TIMESTAMP values. (The time_val table has two

columns for use in time interval calculation examples.)



mysql> SELECT t1, t2 FROM time_val;

+----------+----------+

| t1

| t2

|

+----------+----------+

| 15:00:00 | 15:00:00 |

| 05:01:30 | 02:30:20 |

| 12:30:20 | 17:30:45 |

+----------+----------+

mysql> SELECT d FROM date_val;

+------------+

| d

|

+------------+

| 1864-02-28 |

| 1900-01-15 |

| 1987-03-05 |

| 1999-12-31 |

| 2000-06-04 |

+------------+

mysql> SELECT dt FROM datetime_val;

+---------------------+

| dt

|

+---------------------+

| 1970-01-01 00:00:00 |

| 1987-03-05 12:30:15 |

| 1999-12-31 09:00:00 |

| 2000-06-04 15:45:30 |

+---------------------+

mysql> SELECT ts FROM timestamp_val;

+----------------+

| ts

|

+----------------+

| 19700101000000 |

| 19870305123015 |

| 19991231090000 |

| 20000604154530 |

+----------------+



5.2 Changing MySQL's Date Format

5.2.1 Problem

You want to change the format that MySQL uses for representing date values.



5.2.2 Solution



You can't. However, you can rewrite input values into the proper format when storing dates,

and you can rewrite them into fairly arbitrary format for display by using the DATE_FORMAT(



) function.

5.2.3 Discussion

The CCYY-MM-DD format that MySQL uses for DATE values follows the ISO 8601 standard for

representing dates. This format has the useful property that because the year, month, and

day parts have a fixed length and appear left to right in date strings, dates sort naturally into

the proper temporal order.[1] However, ISO format is not used by all database systems, which

can cause problems if you want to move data between different systems. Moreover, people

commonly like to represent dates in other formats such as MM/DD/YY or DD-MM-CCYY. This

too can be a source of trouble, due to mismatches between human expectations of what dates

should look like and the way MySQL actually represents them.

[1]



Chapters Chapter 6 and Chapter 7 discuss ordering and grouping

techniques for date-based values.

A frequent question from people who are new to MySQL is, "How do I tell MySQL to store

dates in a specific format such as MM/DD/CCYY?" Sorry, you can't. MySQL always stores dates

in ISO format, a fact that has implications both for data entry and for result set display:







For data entry purposes, to store values that are not in ISO format, you normally must

rewrite them first. (If you don't want to rewrite your dates, you'll need to store them

as strings, for example, in a CHAR column. But then you can't operate on them as

dates.) In some cases, if your values are close to ISO format, rewriting may not be

necessary. For example, the string values 87-1-7 and 1987-1-7 and the numbers



870107 and 19870107 all are interpreted by MySQL as the date 1987-01-07 when

loaded into a DATE column. The topic of date rewriting for data entry is covered in

Chapter 10.







For display purposes, you can present dates in non-ISO format by rewriting them.

MySQL's DATE_FORMAT( ) function can be helpful here. It provides a lot of flexibility

for producing whatever format you want (see Recipe 5.3 and Recipe 5.5). You can also

use functions such as YEAR( ) to extract parts of dates (see Recipe 5.6). Additional

discussion may be found in Chapter 10, which includes a short script that dumps table

contents with the date columns reformatted.



5.3 Telling MySQL How to Display Dates or Times

5.3.1 Problem

You want to display dates or times in a format other than what MySQL uses by default.



5.3.2 Solution

Use the DATE_FORMAT( ) or TIME_FORMAT( ) functions to rewrite them.



5.3.3 Discussion

As already noted, MySQL displays dates in ISO format unless you tell it otherwise. To rewrite

date values into other formats, use the DATE_FORMAT( ) function, which takes two

arguments: a DATE, DATETIME, or TIMESTAMP value, and a string describing how to display

the value. Within the formatting string, you indicate what to display using special sequences of

the form %c, where c specifies which part of the date to display. For example, %Y, %M, and %d

signify the four-digit year, the month name, and the two-digit day of the month. The following

query shows the values in the date_val table, both as MySQL displays them by default and

as reformatted with DATE_FORMAT( ):



mysql> SELECT d, DATE_FORMAT(d,'%M %d, %Y') FROM date_val;

+------------+----------------------------+

| d

| DATE_FORMAT(d,'%M %d, %Y') |

+------------+----------------------------+

| 1864-02-28 | February 28, 1864

|

| 1900-01-15 | January 15, 1900

|

| 1987-03-05 | March 05, 1987

|

| 1999-12-31 | December 31, 1999

|

| 2000-06-04 | June 04, 2000

|

+------------+----------------------------+

Clearly, DATE_FORMAT( ) tends to produce rather long column headings, so it's often useful

to provide an alias to make a heading more concise or meaningful:



mysql> SELECT d, DATE_FORMAT(d,'%M %d, %Y') AS date FROM date_val;

+------------+-------------------+

| d

| date

|

+------------+-------------------+

| 1864-02-28 | February 28, 1864 |

| 1900-01-15 | January 15, 1900 |

| 1987-03-05 | March 05, 1987

|

| 1999-12-31 | December 31, 1999 |

| 2000-06-04 | June 04, 2000

|

+------------+-------------------+

The MySQL Reference Manual provides a complete list of format sequences. Some of the more

common ones are shown in the following table:

Sequence



Meaning



%Y



Four-digit year



%y



Two-digit year



%M



Complete month name



%b



Month name, initial three letters



%m



Two-digit month of year (01..12)



%c



Month of year (1..12)



%d



Two-digit day of month (01..31)



%e



Day of month (1..31)



%r



12-hour time with AM or PM suffix



%T



24-hour time



%H



Two-digit hour



%i



Two-digit minute



%s



Two-digit second



%%



Literal %



The time-related format sequences shown in the table are useful only when you pass



DATE_FORMAT( ) a value that has both date and time parts (a DATETIME or TIMESTAMP).

The following query demonstrates how to display DATETIME values from the datetime_val

table using formats that include the time of day:



mysql> SELECT dt,

-> DATE_FORMAT(dt,'%c/%e/%y %r') AS format1,

-> DATE_FORMAT(dt,'%M %e, %Y %T') AS format2

-> FROM datetime_val;

+---------------------+----------------------+----------------------------+

| dt

| format1

| format2

|

+---------------------+----------------------+----------------------------+

| 1970-01-01 00:00:00 | 1/1/70 12:00:00 AM

| January 1, 1970 00:00:00

|

| 1987-03-05 12:30:15 | 3/5/87 12:30:15 PM

| March 5, 1987 12:30:15

|

| 1999-12-31 09:00:00 | 12/31/99 09:00:00 AM | December 31, 1999 09:00:00 |

| 2000-06-04 15:45:30 | 6/4/00 03:45:30 PM

| June 4, 2000 15:45:30

|

+---------------------+----------------------+----------------------------+



TIME_FORMAT( ) is similar to DATE_FORMAT( ), but understands only time-related

specifiers in the format string. TIME_FORMAT( ) works with TIME, DATETIME, or TIMESTAMP

values.



mysql> SELECT dt,

-> TIME_FORMAT(dt, '%r') AS '12-hour time',

-> TIME_FORMAT(dt, '%T') AS '24-hour time'

-> FROM datetime_val;

+---------------------+--------------+--------------+

| dt

| 12-hour time | 24-hour time |

+---------------------+--------------+--------------+

| 1970-01-01 00:00:00 | 12:00:00 AM | 00:00:00

|

| 1987-03-05 12:30:15 | 12:30:15 PM | 12:30:15

|

| 1999-12-31 09:00:00 | 09:00:00 AM | 09:00:00

|

| 2000-06-04 15:45:30 | 03:45:30 PM | 15:45:30

|

+---------------------+--------------+--------------+



5.4 Determining the Current Date or Time

5.4.1 Problem

What's the date? What time is it?



5.4.2 Solution

Use the NOW( ), CURDATE( ), or CURTIME( ) functions.



5.4.3 Discussion

Some applications need to know the current date or time, such as those that produce a

datestamped or timestamped status display. This kind of information is also useful for date

calculations that are performed in relation to the current date, such as finding the first (or

last) day of the month, or determining the date for Wednesday of next week.

The current date and time are available through three functions. NOW( ) returns both the

current date and time. CURDATE( ) and CURTIME( ) return the date and time separately:



mysql> SELECT NOW( ), CURDATE( ), CURTIME( );

+---------------------+------------+-----------+

| NOW( )

| CURDATE( ) | CURTIME( ) |

+---------------------+------------+-----------+

| 2002-07-15 10:59:30 | 2002-07-15 | 10:59:30 |

+---------------------+------------+-----------+



CURRENT_TIMESTAMP and SYSDATE( ) are synonyms for NOW( ). CURRENT_DATE and

CURRENT_TIME are synonyms for CURDATE( ) and CURTIME( ).

If you want to obtain subparts of these values (such as the current day of the month or

current hour of the day), read the next few sections.



NOW( ) Is Not a Valid Column Default Value

Functions such as NOW( ) and CURDATE( ) are commonly (but mistakenly) used in



CREATE TABLE statements as default values:

mysql> CREATE TABLE testtbl (dt DATETIME DEFAULT NOW( ));

You have an error in your SQL syntax near 'NOW( ))' at line 1

The intent here is that values of the dt column should be initialized automatically to

the date and time at which records are created. But it won't work; default values in

MySQL must be constants. If you want a column set to the current date and time at

record creation, use a TIMESTAMP, which MySQL will initialize automatically, or use a



DATETIME and set the initial value yourself when you create records.

The restriction on non-constant default values will be lifted in the future, during the

development of MySQL 4.1.



5.5 Decomposing Dates and Times Using Formatting Functions

5.5.1 Problem



You want to obtain just a part of a date or a time.



5.5.2 Solution

Use a formatting function such as DATE_FORMAT( ) or TIME_FORMAT( ) with a format

string that includes a specifier for the part of the value you want to obtain.



5.5.3 Discussion

MySQL provides several options for decomposing dates or times to obtain their component

values. The DATE_FORMAT( ) and TIME_FORMAT( ) functions provide one way to extract

individual parts of temporal values:



mysql> SELECT dt,

-> DATE_FORMAT(dt,'%Y') AS year,

-> DATE_FORMAT(dt,'%d') AS day,

-> TIME_FORMAT(dt,'%H') AS hour,

-> TIME_FORMAT(dt,'%s') AS second

-> FROM datetime_val;

+---------------------+------+------+------+--------+

| dt

| year | day | hour | second |

+---------------------+------+------+------+--------+

| 1970-01-01 00:00:00 | 1970 | 01

| 00

| 00

|

| 1987-03-05 12:30:15 | 1987 | 05

| 12

| 15

|

| 1999-12-31 09:00:00 | 1999 | 31

| 09

| 00

|

| 2000-06-04 15:45:30 | 2000 | 04

| 15

| 30

|

+---------------------+------+------+------+--------+

Formatting functions allow you to extract more than one part of a value. For example, to

extract the entire date or time from DATETIME values, do this:



mysql> SELECT dt,

-> DATE_FORMAT(dt,'%Y-%m-%d') AS 'date part',

-> TIME_FORMAT(dt,'%T') AS 'time part'

-> FROM datetime_val;

+---------------------+------------+-----------+

| dt

| date part | time part |

+---------------------+------------+-----------+

| 1970-01-01 00:00:00 | 1970-01-01 | 00:00:00 |

| 1987-03-05 12:30:15 | 1987-03-05 | 12:30:15 |

| 1999-12-31 09:00:00 | 1999-12-31 | 09:00:00 |

| 2000-06-04 15:45:30 | 2000-06-04 | 15:45:30 |

+---------------------+------------+-----------+

One advantage of using formatting functions is that you can display the extracted values in a

different form than that in which they're present in the original values. If you want to present

a date differently than in CCYY-MM-DD format or present a time without the seconds part,

that's easy to do:



mysql>

->

->

->



SELECT ts,

DATE_FORMAT(ts,'%M %e, %Y') AS 'descriptive date',

TIME_FORMAT(ts,'%H:%i') AS 'hours/minutes'

FROM timestamp_val;



+----------------+-------------------+---------------+

| ts

| descriptive date | hours/minutes |

+----------------+-------------------+---------------+

| 19700101000000 | January 1, 1970

| 00:00

|

| 19870305123015 | March 5, 1987

| 12:30

|

| 19991231090000 | December 31, 1999 | 09:00

|

| 20000604154530 | June 4, 2000

| 15:45

|

+----------------+-------------------+---------------+

5.5.4 See Also

Recipe 5.6 discusses other functions that may be used to extract single components from

dates or times. Recipe 5.7 shows how to use substring functions for component extraction.



5.6 Decomposing Dates or Times Using Component-Extraction Functions

5.6.1 Problem

You want to obtain just a part of a date or a time.



5.6.2 Solution

Invoke a function specifically intended for extracting part of a temporal value, such as MONTH(



) or MINUTE( ). For obtaining single components of temporal values, these functions are

faster than using DATE_FORMAT( ) for the equivalent operation.



5.6.3 Discussion

MySQL includes many functions for extracting date or time parts from temporal values. Some

of these are shown in the following list; consult the MySQL Reference Manual for a complete

list. The date-related functions work with DATE, DATETIME, or TIMESTAMP values. The timerelated functions work with TIME, DATETIME, or TIMESTAMP values.

Function



Return Value



YEAR( )



Year of date



MONTH( )



Month number (1..12)



MONTHNAME( )



Month name (January..December)



DAYOFMONTH( )



Day of month (1..31)



DAYNAME( )



Day of week (Sunday..Saturday)



DAYOFWEEK( )



Day of week (1..7 for Sunday..Saturday)



WEEKDAY( )



Day of week (0..6 for Monday..Sunday)



DAYOFYEAR( )



Day of year (1..366)



HOUR( )



Hour of time (0..23)



MINUTE( )



Minute of time (0..59)



SECOND( )



Second of time (0..59)



Here's an example:



mysql> SELECT dt,

-> YEAR(dt), DAYOFMONTH(dt),

-> HOUR(dt), SECOND(dt)

-> FROM datetime_val;

+---------------------+----------+----------------+----------+------------+

| dt

| YEAR(dt) | DAYOFMONTH(dt) | HOUR(dt) | SECOND(dt) |

+---------------------+----------+----------------+----------+------------+

| 1970-01-01 00:00:00 |

1970 |

1 |

0 |

0 |

| 1987-03-05 12:30:15 |

1987 |

5 |

12 |

15 |

| 1999-12-31 09:00:00 |

1999 |

31 |

9 |

0 |

| 2000-06-04 15:45:30 |

2000 |

4 |

15 |

30 |

+---------------------+----------+----------------+----------+------------+

Functions such as YEAR( ) or DAYOFMONTH( ) extract values that have an obvious

correspondence to a substring of date values. Some date extraction functions provide access

to values that have no such correspondence. One is the day-of-year value:



mysql> SELECT d, DAYOFYEAR(d) FROM date_val;

+------------+--------------+

| d

| DAYOFYEAR(d) |

+------------+--------------+

| 1864-02-28 |

59 |

| 1900-01-15 |

15 |

| 1987-03-05 |

64 |

| 1999-12-31 |

365 |

| 2000-06-04 |

156 |

+------------+--------------+

Another is the day of the week, which can be obtained either by name or by number:







DAYNAME( ) returns the complete day name. There is no function for returning the

three-character name abbreviation, but you can get it easily by passing the full name

to LEFT( ):























mysql> SELECT d, DAYNAME(d), LEFT(DAYNAME(d),3) FROM date_val;

+------------+------------+--------------------+

| d

| DAYNAME(d) | LEFT(DAYNAME(d),3) |

+------------+------------+--------------------+

| 1864-02-28 | Sunday

| Sun

|

| 1900-01-15 | Monday

| Mon

|

| 1987-03-05 | Thursday

| Thu

|

| 1999-12-31 | Friday

| Fri

|

| 2000-06-04 | Sunday

| Sun

|

+------------+------------+--------------------+







To get the day of the week as a number, use DAYOFWEEK( ) or WEEKDAY( )—but

pay attention to the range of values each function returns. DAYOFWEEK( ) returns

values from 1 to 7, corresponding to Sunday through Saturday. WEEKDAY( ) returns

values from 0 to 6, corresponding to Monday through Sunday.







mysql> SELECT d, DAYNAME(d), DAYOFWEEK(d), WEEKDAY(d) FROM date_val;



Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Chapter 5. Working with Dates and Times

Tải bản đầy đủ ngay(0 tr)

×