Change sqlite to use machine's TZ and not GMT [duplicate] - sqlite

I have a sqlite (v3) table with this column definition:
"timestamp" DATETIME DEFAULT CURRENT_TIMESTAMP
The server that this database lives on is in the CST time zone. When I insert into my table without including the timestamp column, sqlite automatically populates that field with the current timestamp in GMT, not CST.
Is there a way to modify my insert statement to force the stored timestamp to be in CST? On the other hand, it is probably better to store it in GMT (in case the database gets moved to a different timezone, for example), so is there a way I can modify my select SQL to convert the stored timestamp to CST when I extract it from the table?

I found on the sqlite documentation (https://www.sqlite.org/lang_datefunc.html) this text:
Compute the date and time given a unix
timestamp 1092941466, and compensate
for your local timezone.
SELECT datetime(1092941466, 'unixepoch', 'localtime');
That didn't look like it fit my needs, so I tried changing the "datetime" function around a bit, and wound up with this:
select datetime(timestamp, 'localtime')
That seems to work - is that the correct way to convert for your timezone, or is there a better way to do this?

simply use local time as the default:
CREATE TABLE whatever(
....
timestamp DATE DEFAULT (datetime('now','localtime')),
...
);

You should, as a rule, leave timestamps in the database in GMT, and only convert them to/from local time on input/output, when you can convert them to the user's (not server's) local timestamp.
It would be nice if you could do the following:
SELECT DATETIME(col, 'PDT')
...to output the timestamp for a user on Pacific Daylight Time. Unfortunately, that doesn't work. According to this SQLite tutorial, however (scroll down to "Other Date and Time Commands"), you can ask for the time, and then apply an offset (in hours) at the same time. So, if you do know the user's timezone offset, you're good.
Doesn't deal with daylight saving rules, though...

In the (admitted rare) case that a local datatime is wanted (I, for example, store local time in one of my database since all I care is what time in the day is was and I don't keep track of where I was in term of time zones...), you can define the column as
"timestamp" TEXT DEFAULT (strftime('%Y-%m-%dT%H:%M','now', 'localtime'))
The %Y-%m-%dT%H:%M part is of course optional; it is just how I like my time to be stored. [Also, if my impression is correct, there is no "DATETIME" datatype in sqlite, so it does not really matter whether TEXT or DATETIME is used as data type in column declaration.]

When having a column defined with "NOT NULL DEFAULT CURRENT_TIMESTAMP," inserted records will always get set with UTC/GMT time.
Here's what I did to avoid having to include the time in my INSERT/UPDATE statements:
--Create a table having a CURRENT_TIMESTAMP:
CREATE TABLE FOOBAR (
RECORD_NO INTEGER NOT NULL,
TO_STORE INTEGER,
UPC CHAR(30),
QTY DECIMAL(15,4),
EID CHAR(16),
RECORD_TIME NOT NULL DEFAULT CURRENT_TIMESTAMP)
--Create before update and after insert triggers:
CREATE TRIGGER UPDATE_FOOBAR BEFORE UPDATE ON FOOBAR
BEGIN
UPDATE FOOBAR SET record_time = datetime('now', 'localtime')
WHERE rowid = new.rowid;
END
CREATE TRIGGER INSERT_FOOBAR AFTER INSERT ON FOOBAR
BEGIN
UPDATE FOOBAR SET record_time = datetime('now', 'localtime')
WHERE rowid = new.rowid;
END
Test to see if it works...
--INSERT a couple records into the table:
INSERT INTO foobar (RECORD_NO, TO_STORE, UPC, PRICE, EID)
VALUES (0, 1, 'xyz1', 31, '777')
INSERT INTO foobar (RECORD_NO, TO_STORE, UPC, PRICE, EID)
VALUES (1, 1, 'xyz2', 32, '777')
--UPDATE one of the records:
UPDATE foobar SET price = 29 WHERE upc = 'xyz2'
--Check the results:
SELECT * FROM foobar
Hope that helps.

SELECT datetime(CURRENT_TIMESTAMP, 'localtime')

SELECT datetime('now', 'localtime');

Time ( 'now', 'localtime' ) and Date ( 'now', 'localtime' ) works.

You can also just convert the time column to a timestamp by using strftime():
SELECT strftime('%s', timestamp) as timestamp FROM ... ;
Gives you:
1454521888
'timestamp' table column can be a text field even, using the current_timestamp as DEFAULT.
Without strftime:
SELECT timestamp FROM ... ;
Gives you:
2016-02-03 17:51:28

I think this might help.
SELECT datetime(strftime('%s','now'), 'unixepoch', 'localtime');

The current time, in your machine's timezone:
select time(time(), 'localtime');
As per http://www.sqlite.org/lang_datefunc.html

Related

SQLite store current date with time set by defaut to 00:00:00

I have a SQLite table which one of its columns is:
timestamp long DEFAULT CURRENT_TIMESTAMP NOT NULL
It stores in database the UTC date and time but also the time. As time is not important for me how can I store it with time set to 00:00:00 by defaut?
You should use:
timestamp long DEFAULT CURRENT_DATE NOT NULL
By the way - do you know that this format is stored as text (as you may see here)? In many cases, especially when you have reason to index this field, it's more efficient to use INTEGER and just take care and put low-level long date/time representation when inserting/updating
The built-in date functions allow to modify a date value in the way you want:
timestamp text DEFAULT (date('now', 'start of day')) NOT NULL
If you want to store the value as a number, you can convert it appropriately:
timestamp long DEFAULT (strftime('%s', 'now', 'start of day')) NOT NULL

how to apply strftime on localtime

I want to get the day of the month from a datetime column in my Sqlite database. I could use simply
select strftime('%d',myColumn) from myTable
But the values are stored in UTC in the database and i want to get the dates based on the localtime. So i can do the below to get the localtime.
select date(myColumn, 'localtime') from myTable
Now how do i do both these operations together? The only way i can think is by doing inner query with the date() and outer query with strftime(). Is there another way?
The documentation says that modifiers like localtime are used with all date and time functions:
SELECT strftime('%d', myColumn, 'localtime') FROM myTable

sqlite compound where datetime queries

I have a 'presure' table in an sqlite3 database with a 'timestamp' column filled by datetime('now') by a python program which runs periodically adding line at a time to my table.
I'd like to query the database so as to return all the values just from today.
Easy enough:
select * from presure where timestamp like "2014-07-10 %";
BUT, I don't want to have to modify the query each time I run it, today ,tomorrow or any other day. So what I want is someway to replace the date string and wild card with a sub query that generates todays date like:
select date('now');
but I have been unsuccessful compounding the two queries. What am I missing?
In SQL, strings are concatenated with ||:
SELECT * FROM presure WHERE timestamp LIKE date('now') || '%'

How can I store the current timestamp in SQLite as ticks?

I have a SQLite database where I store the dates as ticks. I am not using the default ISO8601 format. Let's say I have a table defined as follows:
CREATE TABLE TestDate (LastModifiedTime DATETIME)
Using SQL, I wish to insert the current date and time. If I execute any of the below statements, I end up getting the date and time stored as a string and not in ticks.
INSERT INTO TestDate (LastModifiedTime) VALUES(CURRENT_TIMESTAMP)
INSERT INTO TestDate (LastModifiedTime) VALUES(DateTime('now'))
I have looked at the SQLite documenation, but I do not seem to find any option to obtain the current timestamp in ticks.
I can of course define a parameter in C# and store the value as a System.DateTime. This does result in the datetime getting stored to the database in ticks.
What I would like to do is be able to insert and update the current timestamp directly from within the SQL statement. How would I do this?
Edit:
The reason I want the data stored as ticks in the database, is that the dates are stored in the same format as stored by the ADO.Net data provider, and so that when the data is also queried using the ADO.Net provider it is correctly retrieved as a System.DataTime .Net type.
This particular oddity of SQLite caused me much anguish.
Easy way - store and retrieve as regular timestamp
create table TestDate (
LastModifiedTime datetime
);
insert into TestDate (LastModifiedTime) values (datetime('now'));
select datetime(LastModifiedTime), strftime('%s.%f', LastModifiedTime) from TestDate;
Output: 2011-05-10 21:34:46|1305063286.46.000
Painful way - store and retrieve as a UNIX timestamp
You can use strftime to retrieve the value in ticks. Additionally, to store a UNIX timestamp (roughly equivalent to ticks), you can can surround the number of seconds in single-quotes.
insert into TestDate (LastModifiedTime) values ('1305061354');
SQLite will store this internally as some other value that is not a UNIX timestamp. On retrieval, you need to explicitly tell SQLite to retrieve it as a UNIX timestamp.
select datetime(LastModifiedTime, 'unixepoch') FROM TestDate;
To store the current date and time, use strftime('%s', 'now').
insert into TestDate (LastModifiedTime) VALUES (strftime('%s', 'now'));
Full example:
create table TestDate (
LastModifiedTime datetime
);
insert into TestDate (LastModifiedTime) values (strftime('%s', 'now'));
select datetime(LastModifiedTime, 'unixepoch') from TestDate;
When executed by sqlite3, this script with print:
2011-05-10 21:02:34 (or your current time)
After further study of the SQLite documentation and other information found on date number conversions, I have come up with the following formula, which appears to produce correct results:
INSERT INTO TestDate(LastModifiedTime)
VALUES(CAST((((JulianDay('now', 'localtime') - 2440587.5)*86400.0) + 62135596800) * 10000000 AS BIGINT))
Seems like a painful way to produce something that I would expect to be available as a built-in datetime format, especially that the database supports the storing of datetime values in ticks. Hopefully, this becomes useful for others too.
Update:
The above formula is not perfect when it comes to daylight savings. See section Caveats And Bugs in SQLite docs regarding local time calculation.
The following will return the number of milliseconds since the UNIX Epoch:
SELECT (strftime('%s', 'now') - strftime('%S', 'now') + strftime('%f', 'now')) * 1000 AS ticks
It works by grabbing the number of seconds since the Unix Epoch (%s), subtracting the number of seconds in the current time (%S), adding the number of seconds with decimal places (%f), and multiplying the result by 1000 to convert from seconds to milliseconds.
The subtraction and addition are to add precision to the value without skewing the result. As stated in the SQLite Documentation, all uses of 'now' within the same step will return the same value.

SQLite - Ordering

I have a strange issue where upon selecting information from a SQLite database, ans ordering based upon date, the results returned are invalid.
My SQL statement is as such:
Select pk from usersDates order by datetime(usersDate, 'localtime') ASC
I have dates stored in the database which range as far as 2111. However the order the data is returned in indicates that dates from 2036 happen after the ones from 2111.
The column 'usersDate is actually a double (time interval since 1970 / unix time) - hence the reason for the cast.
Does anyone know what would cause this?
You should re-read the date and time syntax. The 'localtime' modifier expects an UTC time on its left.
Use SELECT pk FROM usersDates ORDER BY datetime(usersDate, 'unixepoch', 'localtime') ASC.

Resources