MySQL handling over 24h date format - mysql

I'm currently working with a data set that has time formatted over 24h, for example, 27:20:01 (which is 03:20:01). I've been using a query like this STR_TO_DATE(stop_times.arrival_time, "%H:%i:%s") >= STR_TO_DATE("03:14:46", "%H:%i:%s")
to get dates that are not older than current time, but since some dates are formatted over 24h STR_TO_DATE doesn't work. What is the best approach for time formatted like this?

STR_TO_DATE(
CONCAT(
SUBSTRING(stop_times.arrival_time, 1, 2) % 24,
SUBSTRING(stop_times.arrival_time, 3, 8)), "%H:%i:%s")
>= STR_TO_DATE("03:14:46", "%H:%i:%s")

Related

My-SQL inserting Date in format '17-DEC-80'

How can we insert date in in '17-DEC-80' format ?
How to find the last day of this month ?
like this I want to insert 10 dates in the given format and find the last day of the months specified in the date.
This can be acheived through the STR_TO_DATE and DATE_FORMAT internal functions.
You can insert a date so long as you accompany it with the format you are providing it in.
INSERT INTO DateFormats (DF_DATE_FIELD) VALUES (STR_TO_DATE('17-Dec-80', '%d-%b-%y'));
You can also SELECT a that same format date value with the DATE_FORMAT() function. To return the value you want from the table you would use
SELECT
DF_ID,
DF_DATE_FIELD,
DATE_FORMAT(DF_DATE_FIELD, '%d-%b-%y')
FROM DateFormats;
Assuming that DF_DATE_FIELD is in fact a DATE or DATETIME field. Also beware that this is case sensitive
The formatting is as follows
%d = Day of Month for 2 places (i.e 05, 12, 23)
%b = Abbreviated Month (i.e JAN, FEB, DEC)
%y = 2 digit year code (i.e 18, 80, 99)
Read more about formatting At this handy W3 Schools page
And use this DBFiddle for reference
To follow your desired format, use below;
select STR_TO_DATE('17-Dec-80', '%d-%b-%y');
To get last day of the month
select LAST_DAY(STR_TO_DATE('17-Dec-80', '%d-%b-%y'));

How to parse SQL Server binary date format in mysql?

How to convert CAST(0xE3350B00 AS DATE) to mysql ?
I used various forum supports and have following results
0xE3350B00 => 2059-04-03 22:56
0x0000A17F00000000 => 2013-03-12
But both dates belong to same line of data so i am confident that 0xE3350B00 should convert to nearby 2013-03-12 but not finding it technically? Can anyone help if conversion of 0xE3350B00 date??
I used following code in sql function:
return date_add(date_add("1900-01-01 00:00:00", interval conv(substr(HEX(raw_data), 5, 4), 16, 10) DAY), interval conv(substr(HEX(raw_data), 1, 4), 16, 10) MINUTE);
The code you have looks as though it parses SQL Server datetime values (though incorrectly if they have any time part).
This looks like a SQL Server binary date format.
These are stored differently. They occupy three bytes and represents the number of days since 0001-01-01 as a byte reversed integer.
You can use
SELECT
CAST(
'0001-01-01 00:00:00' +
INTERVAL CAST(CONV(
CONCAT(substr(HEX(BinaryData),5,2),
substr(HEX(BinaryData),3,2),
substr(HEX(BinaryData),1,2))
, 16, 10) AS SIGNED) DAY
AS DATE) AS converted_date
FROM
(
SELECT 0xE3350B00 AS BinaryData
) d
Which evaluates to 2012-07-08.
SQL Fiddle

Compare two unix time stamps to see if they are on the same date in MySql

I have read various questions here on Stackoverflow about the use of FROM_UNIXTIME but none directly deal with what I am trying to do. I have one timestamp in a variable coming from php (that has been reformatted - e.g. 25 March 2014) to a function which uses a database query to determine if there are other entries in the database that have the same date (not time). I've run across various methods for formatting and comparing timestamp entries using MySql and ended up with the following but I understand that it isn't very efficient. Does anyone know of a better way to accomplish this?
FROM_UNIXTIME(sd.timestart, "%e %M %Y") = ?'
where the variable in my array for comparison is the date format listed above. This accomplishes what I want but, again, I don't think it is the most efficient way to get this done. Any advice and/or ideas will be much appreciated.
*EDIT*
My timestamp is stored as an integer so I'm trying to use:
$thissessiondate = strtotime($date->timestart, strtotime('today'));
and
$tomorrowdate = strtotime($date->timestart, strtotime('tomorrow'));
to do trim to midnight but get an error (strtotime() expects parameter 2 to be long) and when I move 'today' to the first argument position, I get a conversion to 11 pm instead of 0:00...? I'm making some progress but my very incomplete knowledge of both PHP and MySQL are holding me back.
If you can avoid it, don't wrap columns used in predicates in expressions.
Have your predicates on bare columns to make index range scans possible. You want the datatype conversion to happen over on the literal side of the predicate, wherever possible.
The STR_TO_DATE function is the most convenient for this.
Assuming the timestart column is DATE, DATETIME or TIMESTAMP (which it really should be, if it represents a point in time.)
WHERE sd.timestart >= STR_TO_DATE( ? , "%e %M %Y")
AND sd.timestart < STR_TO_DATE( ? , "%e %M %Y") + INTERVAL 1 DAY
Effectively, what that's doing is taking the string passed in as the first argument to the STR_TO_DATE function, MySQL is going to convert that string to a DATETIME, based on the format specified as the second argument. And that effectively becomes a literal that MySQL can use to compare to the stored values in the column.
If there's an appropriate index available, MySQL will consider an index range scan operation to satisfy that predicate.
You'd need to pass in the same value twice, but that's not really a problem.
On the second line, we're just adding a day to the same value. So what MySQL is seeing is this:
WHERE sd.timestart >= STR_TO_DATE( '25 March 2014' , "%e %M %Y")
AND sd.timestart < STR_TO_DATE( '25 March 2014' , "%e %M %Y") + INTERVAL 1 DAY
In terms of performance, that's equivalent to:
WHERE sd.timestart >= '2014-03-15 00:00:00'
AND sd.timestart < '2014-03-16 00:00:00'
If you do it the other way around, and wrap timestart in a function, that's going to require MySQL to evaluate the function on every single row (or at least, on every row that isn't filtered out by another predicate first.)
IMPORANT NOTE
Be aware that MySQL interprets datetime values as being in the timezone of the MySQL connection, which defaults to the timezone setting of the MySQL server. MySQL is going to interpret datetime literals in the current setting of the timezone. For example, if MySQL timezone is set to +00:00, then datetime literals will be interpreted as UTC.
I assumed the format string matches the data being passed in, I don't use %e or %m. The %Y is a four digit year. (The list of format elements is in the MySQL documentation, under the DATE_FORMAT function.
Reference: http://dev.mysql.com/doc/refman/5.5/en/date-and-time-functions.html#function_str-to-date
If your timestart column is INTEGER or other numeric datatype, representing a number of seconds or some other unit of time since the beginning of an era, you can use the same approach for performance benefits.
In the predicate, reference bare columns from the table, and do any conversions required on the literal side.
If you aren't using MySQL functions to do the conversion to "seconds since Jan 1, 1970 UTC" when rows are inserted (which is really what the TIMESTAMP datatype is doing internally), then I wouldn't recommend using MySQL functions to do the conversion in the query either.
If you're doing the conversion from date and time to an integer type "timestamp" in PHP, then I'd do the inverse conversion in PHP as well, and do the trimming to midnight and the adding of a day in PHP.
In that case, your MySQL query would be of the simple form:
WHERE sd.timestart >= ?
AND sd.timestart < ?
Where you would pass in the appropriate integer values, to compare to the INTEGER timestamp column.
Note that MySQL does provide a function for converting to "seconds since Jan 1 1970 UTC", so if timestart is seconds since Jan 1 1970 UTC, then something like this is valid:
WHERE sd.timestart >= UNIX_TIMESTAMP(STR_TO_DATE( '25 March 2014' , "%e %M %Y"))
AND sd.timestart < UNIX_TIMESTAMP(STR_TO_DATE( '25 March 2014' , "%e %M %Y") + INTERVAL 1 DAY)
BUT... again, be aware of timezone conversion issues; if the MySQL database has a different timezone setting than the web server. If you are going to store "integer", then I wouldn't muck that up with the conversion that MySQL does, which may not be exactly the same as the conversion functions the web server does.
If you store your date as an int timestamp, you can do this
round(sd.timestart/86400)=round(UNIX_TIMESTAMP(NOW())/86400)
This will get everything in your database that is from the same day.
For example:
SELECT id FROM uploads WHERE (approved=0 OR approved is NULL) AND round(uploads.date/86400)<=round(UNIX_TIMESTAMP(NOW())/86400) order by uploads.date DESC LIMIT 20
Will display all the uploads for today and the days before, without showing the future uploads. 86400 is the number of seconds in one day.

Date Comparison Not Working (Dates are strings) - MySQL

I have a MySQL query that reads:
select sum(AmtPd) as HCSA from HC062017 where CostCenter = '8718' and ServiceDate > '08/31/2013'
Have been using it for several months with no problem. Today I encountered a problem with it not working. ServiceDate is a var(10) containing a date pulled from a report. The format is mm-dd-yyyy. What appears to be happening is if the ServiceDate is in 2013 (which some of them still are), then the statement works perfectly. However, when the ServiceDate is in 2014, no records are selected. If I leave off the ServiceDate parameter, I get the desired results (since all records this time are past the 08/31/2013 date). Maybe I lucked out with the months '09', '10', etc, falling after '08'. I've tried using str_to_date with no luck
select sum(AmtPd) as HCSA from HC062017 where CostCenter = '8718' and str_to_date(ServiceDate, '%m, %d, %Y') > '08-31-2013';.
Any suggestions on how to handle this?
You need to convert both to common format:
str_to_date(ServiceDate, '%m-%d-%Y') > str_to_date('08-31-2013', '%m-%d-%Y')
Comparing strings like you did is a bad idea. Strings are compared in alphabetic order, so '08-31-2013' is "smaller" than '09-30-2010' because 9 is compared to 8 before everything else. You can compare dates in ISO format YYYY-MM-DD.
STR_TO_DATE produces a date in a format of YYYY-MM-DD. So your date that you are comparing to must be in the same format:
str_to_date(ServiceDate, '%m, %d, %Y') > '2013-08-31';

SQL - Converting datetime format to 12 hours format with hh:mm:ss

I have a query like,
SELECT CONVERT(VARCHAR, getdate(), 100) AS TwelveHH
output of the above query is Sep 26 2012 6:02PM & i want to get the Hours from the above query means, i will use the query like,
SELECT RIGHT(CONVERT(VARCHAR, getdate(), 100), 7) AS getTime
output of the above query is 6:02PM.
But, i want output with seconds like 6:02:19PM - (hh:mm:ss) format.
How to i get hh:mm:ss format?
Several years ago I wrote this handy guide which still helps me today - mostly because there is no way I am ever going to memorize what all of the different style numbers mean:
SELECT LTRIM(RIGHT(CONVERT(CHAR(20), CURRENT_TIMESTAMP, 22), 11));
In my time zone this returns:
9:12:55 AM
This isn't precisely what you want - you can use REPLACE or STUFF if it's really important to remove that space. e.g.
SELECT REPLACE(LTRIM(RIGHT(CONVERT(CHAR(20), CURRENT_TIMESTAMP, 22), 11)), ' ', '');
In SQL Server 2012, you will be able to do this easier - you can format using parity with C#:
SELECT FORMAT(CURRENT_TIMESTAMP, 'h:mm:ss tt');
EDIT Based on new and changed requirements in the comments below:
SELECT CONVERT(CHAR(11), CURRENT_TIMESTAMP, 109)
+ ' ' + LTRIM(RIGHT(CONVERT(CHAR(20), CURRENT_TIMESTAMP, 22), 11));
Result:
Sep 26 2012 10:03:52 AM
You should do this:
SELECT CONVERT(VARCHAR(10),GETDATE(),108) AS getTime