I use the TIME field quite frequently to store a second-accurate duration. However, how would I store something like:
4 hours, 3 minutes, 1.1828999 second
I would prefer not to store it as a float or decimal, but in a way that is clear it's a time duration. How should I do this?
Store it as a TIME(6) to get up to six digits of precision for fractional seconds. Time precision is a feature introduced in MySQL 5.6.
Storage of fractional seconds costs an extra 3 bytes per column. See https://dev.mysql.com/doc/refman/5.6/en/storage-requirements.html#data-types-storage-reqs-date-time for details.
Then you can format it as you select the value:
mysql> select current_time(6),
date_format(current_time(6), '%H hours, %i minutes, %s.%f seconds') as `formatted time`;
+-----------------+-----------------------------------------+
| current_time(6) | formatted time |
+-----------------+-----------------------------------------+
| 00:24:53.843700 | 00 hours, 24 minutes, 53.843700 seconds |
+-----------------+-----------------------------------------+
See DATE_FORMAT() for other formatting options.
Related
I need to store durations such as the following in mysql:
- 30 seconds
- 20 minutes, 12 seconds
- 1 month
What would be the best way to store this, as the definition of a month can't be reduced, for example, to a number of seconds. My first thought was to store each increment separate, for example:
- num_seconds
- num_minutes
- num_hours
- num_days
- num_months
This could store the above, but I was hoping there was a more direct and less verbose way of doing this.
My first option would be to store duration as a number of seconds with datatype INT. This will make computation and comparison operations fast and clean. Also you can easily compute the duration between two datetime values, by substracting their Unix timestamp. When you need to display the values, you can use mysql sec_to_time function :
However if you are looking to manipulate big durations (months, years), this will not work. In that case I would fallback on a VARCHAR column with iso8601 duration format, like P3Y6M4DT12H30M5S for 3 years, 6 months, 4 days, 12 hours, 30 minutes and 5 seconds. It is a well known format that is supported by many applications (but will be more tedious to manipulate).
Store your intervals for years to months as an integer counting the number of months (12 months = 1 year) and your intervals for days to seconds as an integer of number of seconds.
You can then use the DATE_ADD function to figure out your dates. Here's a SQL Fiddle example showing storing intervals as months and seconds, and adding them to a fixed date:
MySQL 5.6 Schema Setup:
create table mytab (dt date);
insert into mytab values (date '2018-01-01');
create table intervals (months int, seconds int);
insert into intervals values (13, 3661), (-13, -3661);
Query 1:
select dt
, months
, seconds
, date_add(date_add(dt, interval months month)
, interval seconds second) result
from mytab cross join intervals
Results:
| dt | months | seconds | result |
|------------|--------|---------|----------------------|
| 2018-01-01 | 13 | 3661 | 2019-02-01T01:01:01Z |
| 2018-01-01 | -13 | -3661 | 2016-11-30T22:58:59Z |
When saving TIME values into the MySQL database, our server automatically converts these dates to be formatted in UTC time, because of this we've stored our user's timezone offset in our database. Considering we had a simple database like composed of three fields, how would we go about getting the time within the allotted minute range with the appropriate hour.
id | offset | alertTime
---|--------|----------
1 | 360 | 4:22:38
2 | 420 | 3:28:41
In this table, user 1 has a 6 hour offset (CST) and user 2 has a 5 hours offset and a 7 hour offset (MDT) I need to find both of these user's (and any other users) that are all within the same hour after timezone calculation.
The conversion to these user's time is nearly the same, both users have an alert scheduled for 10PM 22Minuts nad 10PM 28 minutes, although different times are entered into the database due to UTC conversion.
Let's say I wanted to get all users who have an alert set for 10PM, between 10:16 and 10:29 CST regardless of their timezone.
Just to clarify, user's who set their alertTime in their own timezone, should be returned if their timezone converts to 10:16 - 10:29 CST. So, 9:16-9:29 MDT would also be returned in these results.
Hope that wasn't too confusing.
--
I'm using MariaDB through NodeJS if that matters.
Don't store them into a TIMESTAMP column; store them as DATETIME. That way, there is no offset during the insert, nor the select.
If you also need UTC, maybe you need two columns, one of each type?
I want to convert seconds to minute : seconds format in sql select statement.
At the moment I am using:
SELECT SEC_TO_TIME(duration) from messages;
It works perfectly but it gives me this format of time: hh:mm:ss
but I need mm:ss
Is it possible to convert seconds into mm:ss format using sql query?
If the value is less than an hour, then just do:
SELECT RIGHT(SEC_TO_TIME(duration), 5) from messages;
If you might go over an hour, then do the arithmetic:
SELECT CONCAT_WS(':', FLOOR(SEC_TO_TIME(duration) / 60),
SEC_TO_TIME(duration) % 60)
I recently had a similar project where I needed to convert stored seconds to m:ss format. No matter the amount, there needed to be at least one digit representing minutes and two digits representing seconds. The hours placeholder was forbidden, so the minutes value could acceptably go beyond 59 and also contain more than 2 digits. The minute value must not be zero-padded.
This is what I used: (SQLFiddle Demo)
CONCAT(FLOOR(seconds/60), ':', LPAD(MOD(seconds,60), 2, 0)) AS `m:ss`
aka
CONCAT(FLOOR(seconds/60), ':', LPAD(seconds%60, 2, 0)) AS `m:ss`
seconds | m:ss
-----------------
0 | 0:00
1 | 0:01
10 | 0:10
60 | 1:00
61 | 1:01
71 | 1:11
3599 | 59:59
3600 | 60:00
5999 | 99:59
6000 | 100:00
TIME_FORMAT(SEC_TO_TIME(seconds),'%i:%s') was unsuitable because the project specifications did not want the minute portion to be zero-padded. Here is a good post relating to this technique.
There is no single-digit minute option in TIME_FORMAT() or DATE_FORMAT().
If you are using MySQL 8.0+ you can use REGEXP_REPLACE like this to achieve a variable length string similar mickmackusa's answer:
REGEXP_REPLACE(SEC_TO_TIME(duration), '^(0|:)+', '')
For example, I have a time format: 1000
how do I convert into MySQL Time() 10:00:00
It can also be more complex, since some numbers are 3 digits long, for example:
900 into MySQL Time() 09:00:00
Let me know if this needs more explaining.
You just want to use str_to_date()
cast your into to a char so its a string and pad it with lpad to keep a leading 0 :)
SELECT STR_TO_DATE(LPAD(CAST(my_col AS CHAR(25)), 4, '0'), '%H') -- or %k
or you can just drop the cast since mysql will do the converting for you
SELECT STR_TO_DATE(LPAD(my_col, 4, '0'), '%k')
FIDDLE
Use CONVERT() -- (http://dev.mysql.com/doc/refman/5.7/en/charset-convert.html)
You'll have to pad it with zeros to show CONVERT() that it is in hours and not minutes.
Specific to your example:
> SELECT CONVERT(CONCAT('1000','00'), TIME) AS time1;
time1
10:00:00
or
> SELECT CONVERT(CONCAT(`fieldname`,'00'), TIME) AS time1 FROM `tablename`;
time1
10:00:00
Select cast(number*100 as time)
Explanation: as mysql documentation on time data type says:
MySQL interprets abbreviated values without colons using the assumption that the two rightmost digits represent seconds (that is, as elapsed time rather than as time of day). For example, you might think of '1112' and 1112 as meaning '11:12:00' (12 minutes after 11 o'clock), but MySQL interprets them as '00:11:12' (11 minutes, 12 seconds). Similarly, '12' and 12 are interpreted as '00:00:12'.
So, if you want to interpret 1000 as 10 hours and 0 minutes, you need to multiply your number by 100 an interpret it as a time expression.
I have a column in a table of type TIME. I want to get a result that applies a time shift that results in a 24 hour clock representation of that shift. To add the shift, my query contains...
select addtime(boo,'01:00:00') as yada
But any value that gets taken out of the 24 hour range ends up outside the 24 hour range, such as...
23:45 ends up as 24:45 (when I want 00:45:00)
If I go the other way and subtract the hour from a value less than 1am, I get...
00:15 ends up as -00:45:00 when I want (23:15:00)
Now, I understand that the TIME format in MYSQL is "duration" and not the actual "time", but for the life of me I can't figure out how to convert to an actual clock time as outlined above. Please help me or kill me. Either will end my suffering.
A simple solution would be to just use a DATETIME data type instead, then ignore the date part. If you're not dealing with huge amounts of data, or searching by the actual times I can't see an issue.
As a bonus you'll be able to manipulate the data with the likes of + INTERVAL 1 HOUR etc.
When extracting it just use TIME(boo)
As you know, the MySQL TIME type is not restricted to 24 hour time so this is probably the closest you'll get... I'm sure you could construct a query using MOD() etc but it's probably not worth it.
A possible solution is just add your boo TIME value to any date (e.g. today) then add your time delta and after that just return time part with TIME()
SELECT TIME(CURDATE()
+ INTERVAL TIME_TO_SEC('23:45:00') SECOND
+ INTERVAL 1 HOUR) new_time
Output:
+----------+
| new_time |
+----------+
| 00:45:00 |
+----------+
Here is SQLFiddle demo