How can I get mysql to output a DateTime to Julian day number? - mysql

Basically I am using the MySQL gem for Ruby, and I have no reasonable support for date comparison. The Mysql::Time class only gives me only accessor methods like year, month, second, etc. I could do much better date comparison, if I could turn this into a Ruby DateTime object. How can convert MySQL's DateTime field to a Julian day number which can be passed to DateTime.jd?

Use:
TO_DAYS(col)+1721060
To convert to julian date.
And:
FROM_DAYS(col-1721060)
to convert from a julian date.
(I'm using the Chronological Julian date which starts at midnight because it's more useful.)

You could use MySQL's TO_DAYS function to get the date as an integer number of days since the year zero (and just add the appropriate offset to have a Julian Day number), or you could use the UNIX_TIMESTAMP function to get an integer number of seconds since 1970-01-01 00:00:00 UTC.

Consider using Ruby/DBI instead of using the MySQL gem directly. Ruby/DBI should take care of the conversion into standard Ruby classes for you automatically, and as an added bonus feature if you ever change the DBMS you're running, your use of the DBI doesn't change.

class Mysql::Time
def to_datetime
DateTime.civil(year,month,day,hour,minute,second)
end
end

This formula is correct from the year 2000 until 2099:
Julian_date = (YEAR(date)-2000)*1000 + DAYOFYEAR(date)

SELECT
DATE_ADD(CONCAT(substring(julian_date,1,2), '-01-01'), INTERVAL substring(julian_date,3,3)-1 DAY)
FROM table

Related

MariaDB UNIX_TIMESTAMP() returns NULL when using dates in the future

I am using UNIX_TIMESTAMP(), but when I pass dates that are far in the future, it starts returning NULL at some point.
For example, the following SQL gives me a proper, non-null result: SELECT UNIX_TIMESTAMP(ADDDATE(NOW(), INTERVAL 18 YEAR)).
However, if I increase that value by one year, the returned value becomes NULL: SELECT UNIX_TIMESTAMP(ADDDATE(NOW(), INTERVAL 19 YEAR))
What is the problem here? Could it be an integer overflow? And how do I solve it?
I am using the following MariaDB version: Ver 15.1 Distrib 10.4.7-MariaDB, for Linux (x86_64) using readline 5.1
Unix time (signed 32-bit) ends on 03:14:07 Tuesday, 19 January 2038 UTC
Related: Year_2038_problem
UNIX_TIMESTAMP:
Timestamps in MariaDB have a maximum value of 2147483647, equivalent to 2038-01-19 05:14:07. This is due to the underlying 32-bit limitation. Using the function on a date beyond this will result in NULL being returned. Use DATETIME as a storage type if you require dates beyond this.
SELECT ADDDATE(NOW(), INTERVAL 19 YEAR) -- DATETIME
-- 2038-09-07 18:42:39
As stated in my above comment I couldn't make it work passed the 2038 Epochalipse date limit, not even converting the field to DATETIME. There are probably other considerations affecting this eventual solution.
The only workaround that I could find was to get the date out of the DB from PHP and use the strtotime() PHP function to get the UNIX TIMESTAMP from it.
SELECT DATE_FORMAT(CONVERT(thedatefield, DATETIME),"%Y-%m-%dT%TZ") AS thedatefield
As there exist different date formats (American, English, Latin, etc...) which are incompatible and a possible source of trouble, I am using two MySQL/ MariaDB functions to flatten the output to an ISO date (YYY-MM-DDThh:mm:ss). Once the output is uniform in any system you can pass the output to the strtotime() PHP function with the confidence that it will be correctly parsed to a UNIX TIMESTAMP.
CONVERT: casts the date to a datetime DB type.
DATE_FORMAT: converts the date to ISO format (YYY-MM-DDThh:mm:ss).
You can of course remove those functions and adapt the solution to the particularities of your system to reduce the processing load. This proposed solution will work with any system date style.
In case of just one register being returned by PHP (the simplest case) I set the first dimension of the returned 2D or table array to 0
date("U",strtotime($php_array[0][thedatefield]))
The PHP date() function by virtue of the "U" flag will convert the DB output to a UNIX TIMESTAMP without the 32 bit 2038 Epochalipse limitation.

How to get Time from Mysql Date Format DD/MM/YYYY?

I want to get time from mysql dd/mm/YYYY H:M:S format.
I have tried,
SUBSTRING_INDEX(field, 'delimiter', index)
but am looking for a better solution.
have tried, DATE_FORMAT(field, "%H:%i:%s") but it returns NULL because my date format was not native (YYYY-mm-dd)
it was 02/05/2019 19:38:27
How to get time from this above format in a better way?
NOTE: I am storing date like above.. this fetching form SQL Server
I guess you can first use STR_TO_DATE followed by CAST(... AS time). Casting instead of formatting allows you to use the result in date/time calculations.
SELECT CAST(STR_TO_DATE('02/05/2019 19:38:27', "%d/%m/%Y %H:%i:%s") AS TIME)
Ideally you should teach SQL Server to export dates in yyyy-MM-dd hh:mm:ss format.
This is how i Resolved,
TIME(STR_TO_DATE(d.in_punch, "%d/%m/%Y %H:%i:%s"))
also as per #Salman A
CAST(STR_TO_DATE('02/05/2019 19:38:27', "%d/%m/%Y %H:%i:%s") AS TIME)
this also worked.

MySQL timestamp format and datediff

Hi I'm writing queries for MySQL, and now my database has a column containing the timestamp in this format: 7/14/2015 7:57:49 AM, but I need to use the DATEDIFF function, so how can I convert the timestamp into the format like: 2015-7-14 (or 2015-07-14, I'm not sure which one is correct; just the date)?
This should convert your string to just the date in a date format, then you can use DATEDIFF on the date fields in question:
SELECT STR_TO_DATE(LEFT(t,LOCATE(' ',t) - 1), '%m/%d/%Y') FROM my_table;
The LEFT function will take the substring to the left of the space, which is just your date, then STR_TO_DATE will convert that substring to a date the system can use.
(Not knowing your field and table names, I used t and my_table.)
You don't need to. The way MySQL displays timestamps has nothing to do with the way they're stored internally; as long as it's TYPE TIMESTAMP or some compatible type, the DATEDIFF() function will know what to do with it.
TIMESTAMPs are actually stored as a really huge integer representing (I think) milliseconds from Midnight UTC, January 1st, 1970. The display format is determined by a system global variable, and has nothing to do with the actual value.
Converting from a string to a DATETIME or TIMESTAMP is actually also fairly straightforward using the STR_TO_DATE() function; in your case the format string would be something like
STR_TO_DATE('%c/%e/%Y %l:%i:%s %p', datecol)
although you might have to experiment a bit to make it work reliably.

MySQL extract HOUR from DATETIME and express in AM/PM

sql newbie here. I googled around for a quick solution to this, but failed to find it.
I have a field that is a DATETIME, for e.g., 2014/06/19 15:07:37. I just need to extract the HOUR and express it in AM/PM, i.e., the above result should read 3pm.
I have tried DATE_FORMAT(HOUR(date_field), %r) but this doesn't work.
date_format() expects a date. hour returns an int. You just need
DATE_FORMAT(date_field, '%l%p')
note that %r is a full time, hh:mm:ss, not just the hour.
You need TIME_FORMAT function:
SELECT TIME_FORMAT(NOW(), "%h%p");

FROM_UNIXTIME does not match DATE_ADD with seconds

Could somebody please explain why this differs?
SELECT
FROM_UNIXTIME(547164000),
DATE_ADD(FROM_UNIXTIME(0), INTERVAL 547164000 SECOND),
##session.time_zone
returns
1987-05-05 00:00:00
1987-05-04 23:00:00
SYSTEM
system's timezone is CEST, +0200 (obtained by command date +%z).
I am using this DATE_ADD method to handle negative timestamp as FROM_UNIXTIME does not support negative values.
A MySQL server can be set up with its own time_zone, such that it doesn't behave like PHP's time(). That is, storing a time() value into a TIMESTAMP field and then displaying the resulting formatted date and time may not give the expected results. You have to be careful not to mix SQL and non-SQL timestamp usage, but stick to one or the other. Why exactly it gives different results for the two expressions is not clear to me, but could point up a bug in MySQL. You would think that adding N seconds to 0 time would give the same results as a plain N time... are you sure that they are formatting under exactly the same time_zone and DST/Summer Time rules?