Timezone independent datetime lookup - sql

As of Sunday we've been running into a problem with our query:
SELECT COUNT(*) / 5 AS count
FROM [dbo].[LogisticalOrderLines_shadow]
WHERE SentToBI >= DATEADD(MINUTE, 55, GETDATE())
This should return the average messages sent per minute (based on the last 5 minutes) However since Monday this query has not been returning the expected results.
We are using our local time zone (was utc+1, now is utc+2) to store the time in our database. In order to prevent having to change this every half year i would like to turn this into a query which always functions no matter the timezone the server is in. but this seems to be quite an issue since we don't store utc times...
How would I go about this if it is even possible.
PS: a very strange thing happened where just for a few hours this morning I had changed the query to use -5 instead of +55 and it actually worked, that was the only way to get the correct amounts. Now however I had to change it again to 115 (which is actually what I would expect, it being UTC +2 and such). So this was quite strange and I do not have an explanation for it.

Related

Trying to reformat timestamp in postgresql

I can't seem to find a question/answer that works for what I'm trying to achieve. Currently, this is how my DB outputs a timestamp:
2015-08-18T19:43:04.738-06:00
However, I would like it to appear as such in the column:
2015-08-18T19:43:04.738 America/Denver
Google has recently changed their formatting options and instead of downloading the output and performing a find/replace, I want an output that doesn't require additional work. I looked on SO and have tried using trim and replace but having no luck.
Thanks for the help in advance!
For whatever reason, the one we've used since February (third from the bottom) no longer works.
2015-08-18T19:43:04.738-06:00 is not quite the right format. Google does not accept milliseconds (which is annoying if they don't just ignore it). You need to send 2015-08-18T19:43:04-06:00. They may have become more strict in what they accept.
Try date_trunc('second', yourtime).
It's not possible to accurately translate an offset like -0600 to a time zone like America/Denver. They say two different things.
-0600 says, with absolute certainty, that this time is 6 hours behind UTC. 12:00:00-06:00 and 18:00:00Z (Z represents UTC) are the same time.
America/Denver means to interpret this timestamp under the rules applicable to the city of Denver, Colorado, USA at that time. To figure out what time it is in UTC you need to look up the offset rules for Denver, Colorado, USA. The offset will change depending on the time of year, usually because of daylight savings time. Because the rules change, it's important to apply the rules as they were at that time.
For example, 2006-03-15 12:00 America/Denver is -0700. But the next year on 2007-03-15 12:00 America/Denver is -0600. Between 2006 and 2007 the daylight savings time rules in the US changed.
Whereas -06:00 avoids all that and simply says the time is offset from UTC by six hours.
You could fake it by simply replacing the offset with America/Denver. So long as you're only sending recent times that should work. You'll be off by at most an hour. But don't do that.
Unless Google Ads specifically needs a time zone there's no point in sending them one. Internally, Postgres is storing your times in UTC anyway and translating them to your server's time zone, America/Denver. Send Google UTC. And, as noted above, chop off the milliseconds.
select date_trunc('second', '2015-08-18T19:43:04.738-06:00'::timestamp with time zone at time zone 'UTC') as datetime;
datetime
---------------------
2015-08-19 01:43:04

Postgres timestamp difference seem to miss 1 hour?

I'm trying to calculate difference between two dates in postgres and found out that on several cases my tests fail, while debugging I found an interesting thing - when I subtract one date from another it seems to lack one hour, here's the script (table has only one timestamp field):
select now(), d1, now() - d1, extract(day from date_trunc('day', now() - d1))
from test;
And here's the result:
This seemed strange, so I decided to check it with some other service and got the result I expected (23 hrs instead of 22):
(see https://www.timeanddate.com/date/durationresult.html?d1=2&m1=3&y1=2019&d2=1&m2=4&y2=2019&h1=23&i1=55&s1=00&h2=23&i2=48&s2=30).
Can somebody explain these results? Am I doing something wrong or missing something obvious? I'm using Postgres 9.6 on macOS.
Many countries switch to daylight savings time between March 2nd and April 1st. Because the clocks move ahead there is one less hour between 2.March.2019 and 1.April.2019.
Beware that Postgres has its own time zone which may not match the user's time zone, especially for a web application. To deal with this, set the application to the user's time zone and the database to UTC. Translate all dates to UTC before passing them to the database.

Time Addition in Sql Server

I have two time value like
Time1=23:59:59:999
Time2=23:59:59:999
when i add up these two time (Time1+Time2) and i want result will be 47:59:58 rather than 23:59:58.
How can i do this? please suggest!!
Let's look at times and durations:
A datetime is a moment in time, say June 28, 1978 at 15:23.
A time without a datepart is a repetitive moment in time, e.g. "I get up every day at 7:00". (This is what you are using. But I get up at 8:00 and go to sleep at 23:00 doesn't make 8 + 23 = 31. It makes no sense to add times.)
Then there is timespan (e.g. from 2016-01-01 3:00 to 2016-01-02 13:00).
And then there is duration (e.g. six minutes). This is what you want to deal with.
You are storing a duration in a time, which is not really the appropriate data type. As SQL Server does not provide a special data type for a duration, you can use a numeric type for this and store seconds or microseconds or whatever you think appropriate. These you can easily add (provided both values have the same unit, e.g. microseconds).
As to displaying the duration you can write a function providing you with the format you like best for a duration (e.g. '913 days, 9 hours, 5 minutes, and 55.123 seconds').
Actually, that is really hard in SQL Server. How about '1 23:59:58'? If so:
select cast(time1 as datetime) + time2
If you actually want the format in HH:MM:SS format, then you will need to do a lot of string manipulation.

Google Bigquery table decorators

I need to add decorators that will represent from 6 days ago till now.
how should I do it?
lets say the date is realative 604800000 millis from now and it's absolute is 1427061600000
#-604800000
#1427061600000
#now in millis - 1427061600000
#1427061600000 - now in millis
Is there a difference by using relative or absolute times?
Thanks
#-518400000--1
Will give you data for the last 6 days (or last 144 hours).
I think all you need is to read this.
Basically, you have the choice of #time, which is time since Epoch (your #1427061600000). You can also express it as a negative number, which the system will interpret as NOW - time (your #-604800000). These both work, but they don't give the result you want. Instead of returning all that was added in that time range, it will return a snapshot of your table from 6 days ago....
Although you COULD use that snapshot, eliminate all duplicates between that snapshot and your current table, and then take THOSE results as what was added during your 6 days, you're better off with :
Using time ranges directly, which you cover with your 3rd and 4th lines. I don't know if the order makes a difference, but I've always used #time1-time2 with time1<time2 (in your case, #1427061600000 - now in millis).

SQL query date according to time zone

We are using a Vertica database with table columns of type timestamptz, all data is inserted according to the UTC timezone.
We are using spring-jdbc's NamedParameterJdbcTemplate
All queries are based on full calendar days, e.g. start date 2013/08/01 and end date 2013/08/31, which brings everything between '2013/08/01 00:00:00.0000' and '2013/08/31 23:59:59.9999'
We are trying to modify our queries to consider timezones, i.e. I can for my local timezone I can ask for '2013/08/01 00:00:00.0000 Asia/Jerusalem' till '2013/08/31 23:59:59.9999 Asia/Jerusalem', which is obviously different then '2013/08/01 00:00:00.0000 UTC' till '2013/08/31 23:59:59.9999 UTC'.
So far, I cannot find a way to do so, I tried setting the timezone in the session:
set timezone to 'Asia/Jerusalem';
This doesn't even work in my database client.
Calculating the difference in our Java code will not work for us as we also have queries returning date groupings (this will get completely messed up).
Any ideas or recommendations?
I am not familiar with Veritca, but some general advice:
It is usually best to use half-open intervals for date range queries. The start date should be inclusive, while the end date should be exclusive. In other words:
start <= date < end
or
start <= date && end > date
Your end date wouldn't be '2013/08/31 23:59:59.9999', it would instead be the start of the next day, or '2013/09/01 00:00:00.0000'. This avoids problems relating to precision of decimals.
That example is for finding a single date. Since you are querying a range of dates, then you have two inputs. So it would be:
startFieldInDatabase >= yourStartParameter
AND
endFieldInDatabase < yourEndParameter
Again, you would first increment the end parameter value to the start of the next day.
It sounds like perhaps Vertica is TZ aware, given that you talked about timestamptz types in your answer. Assuming they are similar to Oracle's TIMESTAMPTZ type, then it sounds like your solution will work just fine.
But usually, if you are storing times in UTC in your database, then you would simply convert the query input time(s) in advance. So rather than querying between '2013/08/01 00:00:00.0000' and '2013/09/01 00:00:00.0000', you would convert that ahead of time and query between '2013/07/31 21:00:00.0000' and '2013/08/31 21:00:00.0000'. There are numerous posts already on how to do that conversion in Java either natively or with Joda Time, so I won't repeat that here.
As a side note, you should make sure that whatever TZDB implementation you are using (Vertica's, Java's, or JodaTime's) has the latest 2013d update, since that includes the change for Israel's daylight saving time rule that goes into effect this year.
Okay, so apparently:
set time zone to 'Asia/Jerusalem';
worked and I just didn't realize it, but for the sake of helping others I'm going to add something else that works:
select fiels at time zone 'Asia/Jerusalem' from my_table;
will work for timestamptz fields