What are the sqlite equivalents of MySQL's INTERVAL and UTC_TIMESTAMP? - mysql

What are the sqlite equivalents of INTERVAL and UTC_TIMESTAMP? For example, imagine you were "porting" the following SQL from MySQL to sqlite:
SELECT mumble
FROM blah
WHERE blah.heart_beat_time > utc_timestamp() - INTERVAL 600 SECOND;

datetime('now') provides you the current date and time in UTC, so is the SQLite equivalent of MySQL's UTC_TIMESTAMP().
It may also be useful to know that given a date and time string, datetime can convert it from localtime into UTC, using datetime('2011-09-25 18:18', 'utc').
You can also use the datetime() function to apply modifiers such as '+1 day', 'start of month', '- 10 years' and many more.
Therefore, your example would look like this in SQLite:
SELECT mumble
FROM blah
WHERE blah.heart_beat_time > datetime('now', '-600 seconds');
You can find more of the modifiers on the SQLite Date and Time Functions page.

There's no native timestamp support in sqlite.
I've used plain old (64-bit) integers as timestamps, representing either micro- or milliseconds since an epoch.
Therefore, assuming milliseconds:
SELECT mumble
FROM blah
WHERE blah.heart_beat_time_millis > ? - 600*1000;
and bind system time in milliseconds to the first param.

there is LOCAL_TIMESTAMP in SQLite, but it's GMT.

Related

Converting Unix timestamp to actual Date and time

Is there any sql command which I can insert into the stated query so I can convert the timestamp. Although it could be done separately which I have seen so far but I am trying to find something which I can add to the stated query as that would be helpful because I am using other queries to retrieve the data as well. If you any other questions please do mention. Addition: rating_timestamp contains both time and date.
SELECT rating_id,
rating_postid,
rating_posttitle,
rating_rating,
rating_timestamp,
rating_username,
rating_userid
FROM wp_ratings;
In cases of date arithmetic, it is especially important to specify the DBMS you are using - Oracle's math is different from Postgres' math is different from SQL Server's math is different from MySQL's math is...
This assumes that you are using SQL Server. Since there is no built in command to do this conversion, you need to create your own function to do that. The function below takes a UNIX / Linux timestamp and converts it to an SQL Server datetime.
CREATE FUNCTION dbo.fn_ConvertToLocalDateTime (#unixdate BIGINT)
RETURNS DATETIME
AS
BEGIN
DECLARE #UTCTimeOffset BIGINT
,#LocalDatetime DATETIME;
SET #UTCTimeOffset = DATEDIFF(second, GETUTCDATE(), GETDATE())
SET #LocalDatetime = DATEADD(second, #unixdate + #UTCTimeOffset, CAST('1970-01-01 00:00:00' AS datetime))
RETURN #LocalDatetime
END;
GO
I wast sure about about Sql version before. This worked perfectly for me.
FROM_UNIXTIME(rating_timestamp,'%h:%i:%s %D %M %Y')

MySQL from_unixtime after 2038-01-19?

We have dates stored as a unix timestamp. To allow a user to search for a certain date - based on his timezone-setting, we used to convert that timestamp inside the query, to make sure a search for "2012-05-03" will not find results of the prior / next day depending on which timezone the user has setup.
i.e. if a date is stored as 2012-05-03 23:00 (UTC) A user with the proper timezone offset searching for 2012-05-04 should find this entry.
This is done like this at the moment:
CONVERT_TZ(FROM_UNIXTIME(`javaTimeStampColumn`/1000),'+00:00','+00:00')
where ofc. the offsets are set depending on the users timezone.
The problem we are facing at the moment: Java successfully stores dates after the year 2038 as a unix-timestamp. The MySQL method from_unixtime however does not support any conversion of values greater than 2147483647 due to it's integer type limitation:
SELECT FROM_UNIXTIME(2147483647); //2038-01-19 04:14:07
SELECT FROM_UNIXTIME(2147483648); //null
The MySQL server itself is 64bit, but ofc. FROM_UNIXTIME would need to accept a long as argument.
I could not find a proper replacement by now, any hints?
We could ofc. load the timestamp as a Long and handle it in the application - But for lazylaoding we need to be able to convert it correctly during the query as well.
A workaround might be to use DATE_ADD, but I'm not sure how it behaves performance-wise:
SELECT DATE_ADD(FROM_UNIXTIME(0), INTERVAL 2147483647 SECOND); //2038-01-19 04:14:07
SELECT DATE_ADD(FROM_UNIXTIME(0), INTERVAL 2147483648 SECOND); //2038-01-19 04:14:08
...
SELECT DATE_ADD(FROM_UNIXTIME(0), INTERVAL 4147483647 SECOND); //2101-06-06 07:47:27
So for now, I'm using
...
CASE
WHEN `javaTimeStampColumn` > 2147483647 THEN
CONVERT_TZ(DATE_ADD(FROM_UNIXTIME(0), INTERVAL `javaTimeStampColumn`/1000 SECOND),'+00:00','+00:00')
ELSE
CONVERT_TZ(FROM_UNIXTIME(`javaTimeStampColumn`/1000), '+00:00','+00:00')
END as ts
FROM table
...
which should minimize the impact on performance if there is any.

DATE_ADD Returning NULL on production server, working in development

Development is localhost running version 5.6.16, production is 5.1.73-cll
The DATE_ADD of this query returns NULL on production, but in development is does exactly what I want it to(adds 90 minutes to the game_time column), The game_time column is a string that contains time in the following format: '21:00'.
This is the query:
SELECT TIME(game_time),
DATE_ADD(TIME(game_time),
INTERVAL 90 MINUTE),
TIME(NOW())
FROM games
What is going on? What am i doing wrong?
I know time should be in a TIMESTAMP, or TIME, but I'm working on someone elses code, I didn't start this from scratch myself.
I've also just noticed that TIME() returns different things, in development, TIME('21:00') returns 21:00:00.000000, in production I only get 21:00:00
Managed to get around, not pretty, but it works.
SEC_TO_TIME(TIME_TO_SEC(TIME(game_time))+5400)
You better develop with the same version as the production server:
Your old version will convert your TIME value to a date and because it's an invalid date, it will get NULL, see manual chapter Conversion Between Date and Time Types
Here's the relevant part:
Before 5.6.4, MySQL converts a time value to a date or date-and-time
value by parsing the string value of the time as a date or
date-and-time. This is unlikely to be useful. For example, '23:12:31'
interpreted as a date becomes '2023-12-31'. Time values not valid as
dates become '0000-00-00' or NULL.
Edit:
To get a TIME value with the desired result, you could use ADDTIME.
This could be working:
SELECT TIME(game_time),
ADDTIME (TIME(CONCAT(CURDATE(), ' ', game_time))),
'01:30:00'),
TIME(NOW())
FROM games
untested, because I have no such old MySQL version anymore.
Try moving the conversion to time outside the DATE_ADD:-
SELECT TIME(game_time), TIME(DATE_ADD(game_time, INTERVAL 90 MINUTE)), TIME(NOW())
FROM games
DATE_ADD works on a DATE or DATETIME field, and as it is you are passing it a TIME field.

Why does the Django time zone setting effect epoch time?

I have a small Django project that imports data dumps from MongoDB into MySQL. Inside these Mongo dumps are dates stored in epoch time. I would expect epoch time to be the same regardless of time zone but what I am seeing is that the Django TIME_ZONE setting has an effect on the data created in MySQL.
I have been testing my database output with the MySQL UNIX_TIMESTAMP function. If I insert a date with the epoch of 1371131402880 (this includes milliseconds) I have my timezone set to 'America/New_York', UNIX_TIMESTAMP gives me 1371131402, which is the same epoch time excluding milliseconds. However if I set my timezone to 'America/Chicago' I get 1371127802.
This is my code to convert the epoch times into Python datetime objects,
from datetime import datetime
from django.utils.timezone import utc
secs = float(epochtime) / 1000.0
dt = datetime.fromtimestamp(secs)
I tried to fix the issue by putting an explict timezone on the datetime object,
# epoch time is in UTC by default
dt = dt.replace(tzinfo=utc)
PythonFiddle for the code
I've tested this Python code in isolation and it gives me the expected results. However it does not give the correct results after inserting these object into MySQL through a Django model DateTimeField field.
Here is my MySQL query,
SELECT id, `date`, UNIX_TIMESTAMP(`date`) FROM table
I test this by comparing the unix timestamp column in the result of this query against the MongoDB JSON dumps to see if the epoch matches.
What exactly is going on here? Why should timezone have any effect on epoch times?
Just for reference, I am using Django 1.5.1 and MySQL-python 1.2.4. I also have the Django USE_TZ flag set to true.
I am no python or Django guru, so perhaps someone can answer better than me. But I will take a guess at it anyway.
You said that you were storing it in a Django DateTimeField, which according to the documents you referenced, stores it as a Python datetime.
Looking at the docs for datetime, I think the key is understanding the difference between "naive" and "aware" values.
And then researching further, I came across this excellent reference. Be sure the read the second section, "Naive and aware datetime objects". That gives a bit of context to how much of this is being controlled by Django. Basically, by setting USE_TZ = true, you are asking Django to use aware datetimes instead of naive ones.
So then I looked back at you question. You said you were doing the following:
dt = datetime.fromtimestamp(secs)
dt = dt.replace(tzinfo=utc)
Looking at the fromtimestamp function documentation, I found this bit of text:
If optional argument tz is None or not specified, the timestamp is converted to the platform’s local date and time, and the returned datetime object is naive.
So I think you could do this:
dt = datetime.fromtimestamp(secs, tz=utc)
Then again, right below that function, the docs show utcfromtimestamp function, so maybe it should be:
dt = datetime.utcfromtimestamp(secs)
I don't know enough about python to know if these are equivalent or not, but you could try and see if either makes a difference.
Hopefully one of these will make a difference. If not, please let me know. I'm intimately familiar with date/time in JavaScript and in .Net, but I'm always interested in how these nuances play out differently in other platforms, such as Python.
Update
Regarding the MySQL portion of the question, take a look at this fiddle.
CREATE TABLE foo (`date` DATETIME);
INSERT INTO foo (`date`) VALUES (FROM_UNIXTIME(1371131402));
SET TIME_ZONE="+00:00";
select `date`, UNIX_TIMESTAMP(`date`) from foo;
SET TIME_ZONE="+01:00";
select `date`, UNIX_TIMESTAMP(`date`) from foo;
Results:
DATE UNIX_TIMESTAMP(`DATE`)
June, 13 2013 13:50:02+0000 1371131402
June, 13 2013 13:50:02+0000 1371127802
It would seem that the behavior of UNIX_TIMESTAMP function is indeed affected by the MySQL TIME_ZONE setting. That's not so surprising, since it's in the documentation. What's surprising is that the string output of the datetime has the same UTC value regardless of the setting.
Here's what I think is happening. In the docs for the UNIX_TIMESTAMP function, it says:
date may be a DATE string, a DATETIME string, a TIMESTAMP, or a number in the format YYMMDD or YYYYMMDD.
Note that it doesn't say that it can be a DATETIME - it says it can be a DATETIME string. So I think the actual value being implicitly converted to a string before being passed into the function.
So now look at this updated fiddle that converts explicitly.
SET TIME_ZONE="+00:00";
select `date`, convert(`date`, char), UNIX_TIMESTAMP(convert(`date`, char)) from foo;
SET TIME_ZONE="+01:00";
select `date`, convert(`date`, char), UNIX_TIMESTAMP(convert(`date`, char)) from foo;
Results:
DATE CONVERT(`DATE`, CHAR) UNIX_TIMESTAMP(CONVERT(`DATE`, CHAR))
June, 13 2013 13:50:02+0000 2013-06-13 13:50:02 1371131402
June, 13 2013 13:50:02+0000 2013-06-13 13:50:02 1371127802
You can see that when it converts to character data, it strips away the offset. So of course, it makes sense now that when UNIX_TIMESTAMP takes this value as input, it is assuming the local time zone setting and thus getting a different UTC timestamp.
Not sure if this will help you or not. You need to dig more into exactly how Django is calling MySQL for both the read and the write. Does it actually use the UNIX_TIMESTAMP function? Or was that just what you did in testing?

How can SELECT UTC_TIMESTAMP() return -10:00 UTC?

Either I'm being stupid or something's wrong here.
I have two SQL Servers, the one is on my local machine (local time +2 GMT) and the other is somewhere else (NOW() seems to return +8 GMT)and I access it through phpMyAdmin. I have a table that has a DATETIME column. I'm trying
to store the current GMT/UTC time and then display it again, still as GMT/UTC time.
Originally I stored DATE_SUB(NOW(), INTERVAL 8 HOUR) which worked just fine. However, then I read about UTC_TIMESTAMP() and liked it more, as it was shorter and the MySQL manual even said :
"The current time zone setting does not affect values displayed by functions
such as UTC_TIMESTAMP() or values in DATE, TIME, or DATETIME columns."
So perfect right? Except no.
Let's assume Current GMT is 2010-02-18 17:18:17 (I even double checked it with someone in Britain).
On my local (+2) server, I get the following results for the following queries:
SELECT NOW(); 2010-02-18 19:18:17
SELECT UTC_TIMESTAMP(); 2010-02-18 17:18:17
On my online server I get:
SELECT NOW(); 2010-02-19 01:18:17
SELECT UTC_TIMESTAMP(); 2010-02-19 07:18:17 (WHY?!)
Am I missing something?!
Probably because the clock are wrong on the online server?
Try running this:
SELECT ##system_time_zone, NOW(), UTC_TIMESTAMP()
and see which zone does it return and does it match the difference.