Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

MYSQL Date Time Round To Nearest Hour

Tags:

datetime

mysql

I have a date time field in a MySQL database and wish to output the result to the nearest hour.

e.g. 2012-04-01 00:00:01 should read 2012-04-01 00:00:00

like image 588
user1217917 Avatar asked Mar 13 '12 07:03

user1217917


People also ask

How do I round a timestamp in SQL?

Rounding or truncating timestamps are especially useful when you're grouping by time. If you are rounding by year, you can use the corresponding function: select year(getdate()) as 'Year'; Be careful if you are grouping by months or smaller timestamp fragments (weeks, days, hours, minutes).

What is interval in MySQL?

MySQL INTERVAL() function returns the index of the argument that is more than the first argument. Syntax: INTERVAL(N,N1,N2,N3,...) It returns 0 if 1st number is less than the 2nd number and 1 if 1st number is less than the 3rd number and so on or -1 if 1st number is NULL. All arguments are treated as an integer.

How do you use timestamp?

The TIMESTAMP data type is used for values that contain both date and time parts. TIMESTAMP has a range of '1970-01-01 00:00:01' UTC to '2038-01-19 03:14:07' UTC. A DATETIME or TIMESTAMP value can include a trailing fractional seconds part in up to microseconds (6 digits) precision.


8 Answers

Update: I think https://stackoverflow.com/a/21330407/480943 is a better answer.


You can do it with some date arithmetic:

SELECT some_columns,
    DATE_ADD(
        DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00"),
        INTERVAL IF(MINUTE(the_date) < 30, 0, 1) HOUR
    ) AS the_rounded_date
FROM your_table

Explanations:

  • DATE_FORMAT: DATE_FORMAT(the_date, "%Y-%m-%d %H:00:00") returns the date truncated down to the nearest hour (sets the minute and second parts to zero).

  • MINUTE: MINUTE(the_date) gets the minute value of the date.

  • IF: This is a conditional; if the value in parameter 1 is true, then it returns parameter 2, otherwise it returns parameter 3. So IF(MINUTE(the_date) < 30, 0, 1) means "If the minute value is less than 30, return 0, otherwise return 1". This is what we're going to use to round -- it's the number of hours to add back on.

  • DATE_ADD: This adds the number of hours for the round into the result.

like image 91
Ben Lee Avatar answered Oct 12 '22 23:10

Ben Lee


Half of the hour is a 30 minutes. Simply add 30 minutes to timestamp and truncate minutes and seconds.

SELECT DATE_FORMAT(DATE_ADD(timestamp_column, INTERVAL 30 MINUTE),'%Y-%m-%d %H:00:00') FROM table

like image 28
rjhdby Avatar answered Oct 12 '22 22:10

rjhdby


soul's first solution truncates instead of rounding and the second solution doesn't work with Daylight Savings cases such as:

select FROM_UNIXTIME(UNIX_TIMESTAMP('2012-03-11 2:14:00') - MOD(UNIX_TIMESTAMP('2012-03-11 2:14:00'),300));

Here is an alternate method (1):

DATE_ADD(
    tick,
    INTERVAL (IF((MINUTE(tick)*60)+SECOND(tick) < 1800, 0, 3600) - (MINUTE(tick)*60)+SECOND(tick)) SECOND
)

If you don't need to worry about seconds you can simplify it like this (2):

DATE_ADD(
    tick,
    INTERVAL (IF(MINUTE(tick) < 30, 0, 60) - MINUTE(tick)) MINUTE
)

Or if you prefer to truncate instead of round, here is simpler version of soul's method (3):

DATE_SUB(tick, INTERVAL MINUTE(tick)*60+SECOND(tick) SECOND)

EDIT: I profiled some of these queries on my local machine and found that for 100,000 rows the average times were as follows:

  • soul's UNIXTIME method: 0.0423 ms (fast, but doesn't work with DST)
  • My method 3: 0.1255 ms
  • My method 2: 0.1289 ms
  • Ben Lee's DATE_FORMAT method: 0.1495 ms
  • My method 1: 0.1506 ms
like image 20
Code Commander Avatar answered Oct 12 '22 22:10

Code Commander


From How to round a DateTime in MySQL?:

It's a little nasty when you do it with datetime data types; a nice candidate for a stored function.

DATE_SUB(DATE_SUB(time, INTERVAL MOD(MINUTE(time),5) MINUTE ), 
         INTERVAL SECOND(time) SECOND)

It's easier when you use UNIXTIME timestamps but that's limited to a 1970 - 2038 date range.

FROM_UNIXTIME(UNIX_TIMESTAMP(time) - MOD(UNIX_TIMESTAMP(time),300))

Good luck.

like image 43
Ghostman Avatar answered Oct 12 '22 23:10

Ghostman


To round down to the current hour, select:

FROM_UNIXTIME(FLOOR(UNIX_TIMESTAMP(column_name) / 3600) * 3600).

The value is expressed in the current time zone doc

like image 42
pawzar Avatar answered Oct 13 '22 00:10

pawzar


This will return the next hour, that is '2012-01-02 18:02:30' will be converted into '2012-01-02 19:00:00'

TIMESTAMPADD(HOUR,
    TIMESTAMPDIFF(HOUR,CURDATE(),timestamp_column_name),
    CURDATE())

Instead of CURDATE() you can use an arbitrary date, for example '2000-01-01' Not sure if there could be problems using CURDATE() if the system date changes between the two calls to the function, don't know if Mysql would call both at the same time.

to get the nearest hour would be:

TIMESTAMPADD(MINUTE,
    ROUND(TIMESTAMPDIFF(MINUTE,CURDATE(),timestamp_column_name)/60)*60,
    CURDATE())

changing 60 by 15 would get the nearest 15 minutes interval, using SECOND you can get the nearest desired second interval, etc.

To get the previous hour use TRUNCATE() or FLOOR() instead of ROUND().

Hope this helps.

like image 27
TMC Avatar answered Oct 13 '22 00:10

TMC


If you need to round just time to next hour you may use this:

SELECT TIME_FORMAT(
  ADDTIME(
    TIMEDIFF('16:15', '10:00'), '00:59:00'
  ),
  '%H:00:00'
)
like image 38
Mikko Avatar answered Oct 12 '22 23:10

Mikko


I think this is the best way, since it also will use the least amount of resources-

date_add(date(date_completed), interval hour(date_completed) hour) as date_hr
like image 34
Dane Thomas Avatar answered Oct 12 '22 22:10

Dane Thomas