I have a sql query for pulling a report from a table. The idea is to pull the sum of counts, grouped by day of the week, in the local timezone. Dates in the table are stored in UTC.
SELECT (SUM(t.di1) + SUM(t.di2) + SUM(t.di3) + SUM(t.di4)) AS [ScanCount],
DATEPART(WEEKDAY, t.LocalTime) AS [weekday]
FROM (SELECT di1,
di2,
di3,
di4,
CreatedOnUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' AS LocalTime
FROM tableName
WHERE DeviceId = 649754) t
WHERE t.LocalTime > '03/16/2020 00:00'
AND t.LocalTime < '03/16/2020 23:59:59'
GROUP BY DATEPART(WEEKDAY, t.LocalTime)
ORDER BY DATEPART(WEEKDAY, t.LocalTime);
A query like this should only return a single day of the week count, but it returns 2 days. This obviously has something to do with the difference in time zones, whereas the UTC time contains dates from both 3/15 and 3/16. It seems that the conversion from UTC to Pacific Time works in the output but the UTC values are used in the where clause. How can I do this comparison to the new converted datetimes and not to the original UTC times?
Comparison between datetimeoffset and string literal works in UTC.
Simplest solution will be to convert datetimeoffset to datetime2.
Modify your inner query to:
cast(CreatedOnUTC AT TIME ZONE 'UTC' AT TIME ZONE 'Pacific Standard Time' as datetime2(0)) AS LocalTime
I want to get the data from the last 28 days and only include complete days. So what I mean is, when I look at the data today at 10:00 AM, it only includes data from yesterday (the completed day) and 28 days before yesterday.
I am creating a live dashboard with figures like this. So I don't want the numbers to change until the day is finished.
Also, I am willing to understand the difference between CURRENT_DATE and CURRENT_TIMESTAMP
For example, in my code, if I use CURRENT_TIMESTAMP, will I get the data from today 10:00 AM back to 28 days ago 10:00 AM? if not, how can I get data in a way numbers change live according to every time I run the code (the average time that data change in the database is 10 minutes).
My simplified code:
select count(id) from customers
where created_at > CURRENT_DATE - interval '28 days'
Maybe I am using wrong code, can you please give me advice on how to get the date in both formats:
include only complete days(does not include today, until the day is
finished)
include hours, from today morning until 28 days back same
time in the morning.
Assuming created_at is of type timestamptz.
include only complete days(does not include today, until the day is
finished)
Start with now() and use date_trunc():
SELECT count(*)
FROM customers
WHERE created_at < date_trunc('day', now())
AND created_at >= date_trunc('day', now() - interval '28 days');
Or work with CURRENT_DATE ...
WHERE created_at < CURRENT_DATE
AND created_at >= CURRENT_DATE - 28;
The result for both depends on the current timezone setting. The "date" functionally depends on your current time zone. The type timestamp with time zone (timestamptz) does not. But the expression date_trunc('day', now()) introduces the same dependency as the "day" is defined by your current time zone. So you need to define which "days" you mean precisely. Basics:
Ignoring time zones altogether in Rails and PostgreSQL
You can subtract integer values from a date to subtract days:
How do I determine the last day of the previous month using PostgreSQL?
now() is a shorter equivalent of CURRENT_TIMESTAMP. See:
Difference between now() and current_timestamp
count(*) is equivalent to count(id) while id is defined NOT NULL, but a bit faster.
I have different results from query for COUNT('e.id') or COUNT(e.id)
include hours, from today morning until 28 days back same time in the morning.
Simply:
WHERE created_at > now() - interval '28 days'
No dependency on the current time zone.
I am trying to include, in my where clause, a way to automatically pull data for the previous day based on my current timezone. All of my data is stored with a UTC timestamp.
I can change my timestamp from UTC to my timezone ("America/Chicago") and I can automatically pull data for the last X days; for example, for the prior week, without having to manually enter a date. But I cannot figure out how to do both simultaneously in my where clause.
SELECT *
FROM `my-data-set`
WHERE
event_time >= CAST(DATE_SUB(CURRENT_DATE(), INTERVAL 7 DAY) AS TIMESTAMP)
AND event_time < CAST(DATE_SUB(CURRENT_DATE(), INTERVAL 0 DAY) AS TIMESTAMP)
I would like to be able to look at the previous week or day in my timezone, not the previous UTC day.
You can do specify the timezone:
where date(event_time, 'America/Chicago') = date_add(current_date, interval -1 day)
Note that the parentheses are not needed for current_date.
The key to the logic is converting the UTC timestamp to a date in your local time.
In big query how do I get the yesterday date with the time part 00:00:00?
DATE Doesn't have time part
if you want yesterday DateTime with 00:00 as time use:
SELECT DATETIME_TRUNC(DATETIME_SUB(CURRENT_DATETIME(), INTERVAL 1 DAY), DAY) as yesterday;
if you want yesterday date use:
SELECT DATE_SUB(CURRENT_DATE(), INTERVAL 1 DAY) as yesterday;
If you want a time part, then you want either a TIMESTAMP or DATETIME column.
So, either:
SELECT DATETIME(DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) as yesterday_dt,
TIMESTAMP(DATE_ADD(CURRENT_DATE(), INTERVAL -1 DAY)) as yesterday_ts
This code gets you date
SELECT DATEADD(dd, -1, DATEDIFF(dd, 0, GETDATE()));
For different methods check this link
MS SQL Server - How to get Date only from the datetime value?
Below is yet another option for BigQuery standard SQL
#standardSQL
SELECT
TIMESTAMP_SECONDS(86400 * (UNIX_DATE(CURRENT_DATE()) - 1)) yesterday_as_timestamp,
DATETIME(TIMESTAMP_SECONDS(86400 * (UNIX_DATE(CURRENT_DATE()) - 1))) yesterday_as_datetime
with result (as of answer day - April 02, 2019)
Row yesterday_as_timestamp yesterday_as_datetime
1 2019-04-01 00:00:00 UTC 2019-04-01T00:00:00
Note:
DATETIME Represents a year, month, day, hour, minute, second, and subsecond. Range: 0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999.
TIMESTAMP Represents an absolute point in time, with microsecond precision. Range: 0001-01-01 00:00:00 to 9999-12-31 23:59:59.999999 UTC.
A timestamp represents an absolute point in time, independent of any time zone or convention such as Daylight Savings Time.
TIMESTAMP provides microsecond precision.
Unlike Timestamps, a DATETIME object does not refer to an absolute instance in time. Instead, it is the civil time, or the time that a user would see on a watch or calendar.
You can see more details about DATETIME and TIMESTAMP in Data Types doc
I would like to convert getdate() in SQL Server to EST time.
UPDATED ANSWER (05-29-2020)
The Azure SQL team has released a new function which makes this even easier. SELECT CURRENT_TIMEZONE_ID() will return your server's timezone. Adding this function into the ORIGINAL ANSWER below yields a single query will work globally on all Azure SQL Servers.
SELECT CONVERT(DATETIME,GETDATE() AT TIME ZONE (SELECT CURRENT_TIMEZONE_ID()) AT TIME ZONE 'Eastern Standard Time')
This query will work on any Azure SQL Server.
ORIGINAL ANSWER:
There are a lot of answers here that are unnecessarily complex, or that don't account for daylight savings time. No massive CASE statements needed. No new stored procedure, or scalar/user defined functions are needed. As of SQL Server 2016, converting between timezones can be done with a single line of native sql. This has advantages. For example, it can be called from reports or used on databases that are read-only.
SELECT CONVERT(DATETIME,GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time')
That's it. Above, we are using the AT TIME ZONE features, described in more detail here. There may be some functions and features that are new here, so an explanation is warranted. The query above calls GETDATE() and sets it's timezone as UTC using AT TIMEZONE. Implicitly, this is also changing it's datatype from a datetime to datetimeoffset. Next, we'll call AT TIMEZONE again to cut it over to EST. Lastly, we'll wrap the entire thing in CONVERT() to get it back to a datetime, dropping the unneeded +/- hours portion during the process.
Taking the query step-by-step ...
SELECT [GetDate] = GETDATE()
SELECT [GetDateAtUtc] = GETDATE() AT TIME ZONE 'UTC'
SELECT [GetDateAtUtcAtEst] = GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'
SELECT [GetDateEst] = CONVERT(DATETIME,GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time')
Have you considered GETUTCDATE() and performing the offset from there?
If you mean EST as in standard time, then that is UTC-5, so
select dateadd(hour,-5,GETUTCDATE())
SQL server itself has the table current_utc_offset with correct offset for summer and winter time.
Please, try the query select * from current_utc_offset, change the date to different season on your server and review the table again.
So the correct function to get EST would be:
CREATE FUNCTION [dbo].[Getestlocaldatetime] ()
returns DATETIME
AS
BEGIN
DECLARE #zz NVARCHAR(12);
DECLARE #hh NVARCHAR(3);
DECLARE #dd DATETIME;
SET #zz = (SELECT current_utc_offset
FROM sys.time_zone_info
WHERE NAME = N'US Eastern Standard Time')
SET #hh = Substring(#zz, 1, 3);
SET #dd = Dateadd(hh, CONVERT(INT, #hh), Getutcdate())
RETURN #dd
END
EST is GMT-5 hours while EDT is GMT-4 hours.
To get EST:
select dateadd(hour,-5,GETUTCDATE())
To get EDT :
select dateadd(hour,-4,GETUTCDATE())
SELECT CONVERT(VARCHAR, CONVERT(DATETIME, GETDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time'), 100) AS [Date_Result]
https://stackoverflow.com/a/49449695/6559330
using GETDATE() :
GMT :
DATE WILL BE DISPLAYED:
SELECT GETDATE()
EST :
USE GETDATE() FOR CONVERSION NOW:
SELECT DATEADD(HOUR, -4, CONVERT(varchar(20),GETDATE(),120))
If you are attempting to output a local time, such as eastern time, with Daylight savings time, you need a function that Detects the start and end of daylight savings time and then applies a variable offset: I've found this: http://joeyiodice.com/convert-sql-azure-getdate-utc-time-to-local-time/ useful.
GetDate() is the system time from the server itself.
Take the hour difference of the GetDate() now and the time it is now in EST use this code where 1 is that said difference ( in this instance the server is in Central Time zone) (This is also assuming your server is accounting for DST)
SELECT Dateadd(hour, 1, Getdate()) AS EST
For those who are using latest version of sql server can create a .net function
A scalar-valued function (SVF) returns a single value, such as a string, integer, or bit value. You can create scalar-valued user-defined functions in managed code using any .NET Framework programming language. These functions are accessible to Transact-SQL or other managed code. For information about the advantages of CLR integration and choosing between managed code and Transact-SQL.
Since .NET has access to all time zone at operating system so you don't have to calculate daylight saving -4 or -5 fundamentals.
var timeUtc = DateTime.UtcNow;
TimeZoneInfo easternZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime easternTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, easternZone);
Select CONVERT(DATETIME,GETUTCDATE() AT TIME ZONE 'UTC' AT TIME ZONE 'Eastern Standard Time')
If you want to do this without calling a function, you can do it with a CASE statement as well. The code below converts a UTC field to Mountain Time accounting for daylight savings. For EST, you would just change all the -6 to -4 and change all the -7 to -5.
--Adjust a UTC value, in the example the UTC field is identified as UTC.Field, to account for daylight savings time when converting out of UTC to Mountain time.
CASE
--When it's between March and November, it is summer time which is -6 from UTC
WHEN MONTH ( UTC.Field ) > 3 AND MONTH ( UTC.Field ) < 11
THEN DATEADD ( HOUR , -6 , UTC.Field )
--When its March and the day is greater than the 14, you know it's summer (-6)
WHEN MONTH ( UTC.Field ) = 3
AND DATEPART ( DAY , UTC.Field ) >= 14
THEN
--However, if UTC is before 9am on that Sunday, then it's before 2am Mountain which means it's still Winter daylight time.
CASE
WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1
AND UTC.Field < '9:00'
--Before 2am mountain time so it's winter, -7 hours for Winter daylight time
THEN DATEADD ( HOUR , -7 , UTC.Field )
--Otherwise -6 because it'll be after 2am making it Summer daylight time
ELSE DATEADD ( HOUR , -6 , UTC.Field )
END
WHEN MONTH ( UTC.Field ) = 3
AND ( DATEPART ( WEEKDAY , UTC.Field ) + 7 ) <= DATEPART ( day , UTC.Field )
THEN
--According to the date, it's moved onto Summer daylight, but we need to account for the hours leading up to 2am if it's Sunday
CASE
WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1
AND UTC.Field < '9:00'
--Before 9am UTC is before 2am Mountain so it's winter Daylight, -7 hours
THEN DATEADD ( HOUR , -7 , UTC.Field )
--Otherwise, it's summer daylight, -6 hours
ELSE DATEADD ( HOUR , -6 , UTC.Field )
END
--When it's November and the weekday is greater than the calendar date, it's still Summer so -6 from the time
WHEN MONTH ( UTC.Field ) = 11
AND DATEPART ( WEEKDAY , UTC.Field ) > DATEPART ( DAY , UTC.Field )
THEN DATEADD ( HOUR , -6 , UTC.Field )
WHEN MONTH ( UTC.Field ) = 11
AND DATEPART ( WEEKDAY , UTC.Field ) <= DATEPART ( DAY , UTC.Field )
--If the weekday is less than or equal to the calendar day it's Winter daylight but we need to account for the hours leading up to 2am.
CASE
WHEN DATEPART ( WEEKDAY , UTC.Field ) = 1
AND UTC.Field < '8:00'
--If it's before 8am UTC and it's Sunday in the logic outlined, then it's still Summer daylight, -6 hours
THEN DATEADD ( HOUR , -6 , UTC.Field )
--Otherwise, adjust for Winter daylight at -7
ELSE DATEADD ( HOUR , -7 , UTC.Field )
END
--If the date doesn't fall into any of the above logic, it's Winter daylight, -7
ELSE
DATEADD ( HOUR , -7 , UTC.Field )
END