SQL SERVER Convert UTC DATETIME to local date time - sql

I have a table with the column CreatedDateTime as shown below :
[CREATED_DATE_TIME] [datetime] NOT NULL DEFAULT GETUTCDATE()
When I am retrieving the created date time, it is giving me datetime value in UTC, but I want to show the datetime value in local time.
How can this be achieved?
Looking forward to your answers and thanks in advance.

Try like below
— Convert a UTC Time to a Local Time
DECLARE #UTCDate datetime
DECLARE #LocalDate datetime
DECLARE #TimeDiff int
— Figure out the time difference between UTC and Local time
SET #UTCDate = GETUTCDATE()
SET #LocalDate = GETDATE()
SET #TimeDiff = DATEDIFF(hh, #UTCDate, #LocalDate)
— Convert UTC to local time
DECLARE #DateYouWantToConvert datetime
DECLARE #ConvertedLocalTime datetime
SET #DateYouWantToConvert = '4/25/2007 18:00'
SET #ConvertedLocalTime = DATEADD(hh, #TimeDiff, #DateYouWantToConvert)
— Check Results
PRINT #ConvertedLocalTime

Related

Modify JSON string in SQL (datetime entry)

I have a table like this:
| Id | Data | TimeStamp
-- Example info. Check Data EOL to see Time
| Id | 732DC7DE-2B9D-4B91-8753-0004128B26D2
| Data | {"message":"Machine is down","machineId":"165ACE37-4E2C-4D44-9D14-D4D3ABK66C","machineName":"1501","ipAddress":"192.168.0.1","time":"2018-05-20T18:33:23.171"}
| TimeStamp | 2018-05-20 18:33:23.1710000
I need to convert the datetime values in this table to UTC time.
I've figured out the TimeStamp conversion.
Update ProcessEventMessage SET TimeStamp = DateADD(hour, -2, TimeStamp)
My local is UTC+2h I.E. I have to remove 2h from the json-data.
But I have no idea how to convert the json-datetime object into UTC.
I've tried something like this but without success. How would I accomplish converting these numbers into UTC? (i.e. remove two hours).
"time":"2018-05-20T18:33:23.171"
Read more about ISO_8601 Here Structure: YYYY-MM-DDTHH:MM:SS.MSS
TL;DR: Remove 2h from the json string
Thoughts: one way to do this, would be to look for the T in the time, and replace the hours after it to deduct 2h. (possible?)
EDIT:
I've now got a structured query of the sql-table like this:
DECLARE #json NVARCHAR(MAX) = {"message":"Machine is down","machineId":"165ACE37-4E2C-4D44-9D14-F9E2CB2C2C13","machineName":"1501","ipAddress":"192.168.150.101","time":"2018-05-20T18:33:23.171"}
SELECT * FROM OPENJSON(#json)
WITH ( message varchar(200) '$.message',
machineId varchar(200) '$.machineId',
machineName int '$.machineName',
ipAddress varchar(200) '$.ipAddress',
time datetime2(7) '$.time'
)
Can i somehow use these variables to modify the value?
Try something like this:
DECLARE #UTCDateTime DATETIME = GETUTCDATE();
SET #UTCDateTime = TimeStamp AT TIME ZONE 'your time zone' AT TIME ZONE 'UTC'
SET #UTCDateTime = TimeStamp AT TIME ZONE 'Central Europe Standard Time' AT TIME ZONE 'UTC'
select #UTCDateTime
(AT TIME ZONE) works on only SQL Server 2016+
DECLARE #JSON NVARCHAR(MAX)
SET #JSON =
'{
"TMP": [
{"message":"Machine is down","machineId":"165ACE37-4E2C-4D44-9D14-F9E2CB2C2C13","machineName":"1501","ipAddress":"192.168.150.101","time":"2018-05-20T18:33:23.171"}]}
'
SET #JSON = JSON_MODIFY(#JSON, '$.TMP[0]', 'something')

SQL date conversion HHMMSS.CCCNNNNNN to yyyy-mm-dd hh:mi:ss.mmm

I have data in this format : 114643.052303537 (HHMMSS.CCCNNNNNN).
I need to convert it to this format : 2018-04-25 12:40:59.573 (yyyy-mm-dd hh:mi:ss.mmm), strip of the date part ( i.e. 2018-04-25 ) and calculate the time difference between two formats.
Could you please help with this?
I need the time difference in hh:mi:ss.mmm format
The way to get this is to convert BOTH values to milliseconds (looking at only the time portion for the value that has a date); calculate the difference with simple subtraction, and then convert the result to hh:mi:ss.mmm with division and modulo operations.
declare #dt datetime = '2018-04-25 12:40:59.573'
declare #dunno varchar(16) = '114643.052303537'
Strip the date off the datetime and give it today's date
getdate() + right(convert(varchar,#dt,113),12)
Convert the varchar to time and give it today's date
getdate() + left(stuff(stuff(#dunno,3,0,':'),6,0,':'),8)
Find the milliseconds between them
datediff(millisecond,getdate() + left(stuff(stuff(#dunno,3,0,':'),6,0,':'),8),getdate() + right(convert(varchar,#dt,113),12))
Put it all together in your format
select
convert(char(13),
dateadd(millisecond,
datediff(millisecond,getdate() + left(stuff(stuff(#dunno,3,0,':'),6,0,':'),8),getdate() + right(convert(varchar,#dt,113),12)),
'01/01/00'),
14)
Depending on the speed of your server and other code, it'd be wise to use a variable for GETDATE() at the beginning to prevent millisecond, or even second differences during conversion.
declare #dt datetime = '2018-04-25 12:40:59.573'
declare #dunno varchar(16) = '114643.052303537'
declare #today datetime = getdate()
declare #dunno2 datetime
declare #dt2 datetime
set #dt2 = #today + right(convert(varchar,#dt,113),12)
set #dunno2 = #today + left(stuff(stuff(#dunno,3,0,':'),6,0,':'),8)
select
convert(char(13),
dateadd(millisecond,
datediff(millisecond,#dunno2,#dt2),
'01/01/00'),
14)

Get DAY from Date

I need select day from #ReportDay
DECLARE #ReportDay DATETIME = '2017-10-02 12:00:03.140'
DECLARE #currentReportDay DATETIME = DATEPART(day, #ReportDay )
But in result I've '1900-01-03 00:00:00.000'. How it can be fix?
DECLARE #ReportDay DATETIME = FORMAT(Now(),'YYYY-MM-DD')
DECLARE #currentReportDay DATETIME = DATEPART(day, #ReportDay)
This would give you today's date in YYYY-MM-DD format
DATEPART gives you back an integer
DECLARE #ReportDay DATETIME = '2017-10-02 12:00:03.140'
DECLARE #currentReportDay INT = DATEPART(day, #ReportDay )
Others have already raised the ambiguity of your question but to add some explanation and hopefully clear up some confusion.
The reason why you are getting '1900-01-03 00:00:00.000'
is because DATEPART(day, #ReportDay) will return an integer for the day of the month, in your case 2. When converted to a DATETIME 2 is actually the 3rd date. 0 is 1/1/1900, 1 is 1/2/1900. and so forth.
So if you want the DATE itself you can use CONVERT or CAST. Some other string manipulation techniques exist and FORMAT() is one of them but they are not worth looking at as will have much poorer performance and take additional CASTS and CONVERTS anyway. What you want to do is to DROP the TIME off the DATETIME. Best way of doing that is to CAST it to a DATE which has no TIME component.
DECLARE #currentReportDay DATETIME = CAST(CAST(#ReportDay AS DATE) AS DATETIME)
Note because the second CAST back to DATETIME isn't really necessary in this code as it will inherently happen so you could shorten to:
DECLARE #currentReportDay DATETIME = CAST(#ReportDay AS DATE)
And to round this out. If you actually want the DAY of the Month then simply change from DATETIME data type to INT.
DECLARE #currentReportDay INT = DATEPART(day, #ReportDay )

Transforming nvarchar day duration setting into datetime

I have a SQL Server function which converts a nvarchar day duration setting into a datetime value.
The day duration format is >days<.>hours<:>minutes<, for instance 1.2:00 for one day and two hours.
The format of the day duration setting can not be changed, and we can be sure that all data is correctly formatted and present.
Giving the function a start time and the day duration setting it should return the end time.
For instance: 2010-01-02 13:30 ==> 2010-01-03 2:00
I'm using a combination of charindex, substring and convert methods to calculate the value,
which is kind of slow and akward. Is there any other way to directly convert this day duration setting into a datetime value?
Not from what I can see. I would end up with a similar bit of SQL like you, using charindex etc. Unfortunately it's down to the format the day duration is stored in. I know you can't change it, but if it was in a different format then it would be a lot easier - the way I'd usually do this for example, is to rationalise the duration down to a base unit like minutes.
Instead of storing 1.2:00 for 1 day and 2 hours, it would be (1 * 24 * 60) + (2 * 60) = 1560. This could then be used in a straightforward DATEADD on the original date (date part only).
With the format you have, all approaches I can think of involve using CHARINDEX etc.
One alternative would be to build a string with the calculation. Then you can run the generated SQL with sp_executesql, specifying #enddate as an output parameter:
declare #startdate datetime
declare #duration varchar(10)
declare #enddate datetime
set #startdate = '2010-01-02 13:30'
set #duration = '0.12:30'
declare #sql nvarchar(max)
set #sql = 'set #enddate = dateadd(mi,24*60*' +
replace(replace(#duration,'.','+60*'),':','+') + ', #startdate)'
exec sp_executesql #sql,
N'#startdate datetime, #enddate datetime out',
#startdate, #enddate out
This creates a string containing set #enddate = dateadd(mi,24*60*0+60*12+30, #startdate) and then runs it.
I doubt this is faster than the regular charindex way:
declare #pos_dot int
declare #day int
declare #hour int
declare #minute int
select
#pos_dot = charindex('.',#duration),
#day = cast(left(#duration, #pos_dot-1) as int),
#hour = cast(left(right(#duration, 5), 2) as int),
#minute = cast(right(#duration, 2) as int),
#enddate = dateadd(mi, 24*60*#day + 60*#hour + #minute, #startdate)

Limiting a date range with exactness in MS SQL / SQL Server 2005

I want to limit a report to return records from Date A through Date B. This is what I have been doing:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008'
set #endDate = '04/01/2008'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections
where date between #startDate and #endDate
... which I was told returned records from 12 am Jan 1st through 11:59 pm March 31st (that midnight is the default when no time is indicated). But I noticed a discrepancy, which is if a record has a time of 00:00:00 that it will be part of this set.
Is there a more exact way of doing this so it will return exactly the date range I want?*
I tried using time:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008 00:00:00'
set #endDate = '04/01/2008 11:59:59'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections
where date between #startDate and #endDate
... but I noticed something wonky: SQL Server will ROUND the hundreth-second up by half. So I get that April 1st record (ha! April Fool's record! grr) if I use any time later than 11:59:29. Why is that?
(I feel sure there is. I'm new at this. Thanks for your help!)
There's always the easy option:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008'
set #endDate = '04/01/2008'
-- test what are the start and end dates
select min(date),max(date) from view_Inspections
where date >= #startDate
and date < #endDate
I suspect that the date column in view_Inspections is a SmallDateTime data type. This data type has 1 minute accuracy, which explains your unexpected results (rounding the seconds to the nearest minute).
The method Roland Shaw suggests is the best way to modify your query to accommodate your requirements.
The BETWEEN operator is inclusive, which is why you're seeing the results that you are in your first query. The rounding that you're seeing in your second query is going to be dependent on what exact datetime data type you are using in your table. (BTW, I think you're confusing seconds with hundredths of seconds). It looks like you're probably using a smalldatetime in your table, in which case the time is rounded to the nearest minute.
If your table is using datetime, try explicitly converting your #startDate and #endDate to DATETIME values (CAST(#endDate AS DATETIME)).
A quick note... even for DATETIME values, SQL Server is only accurate to the 3/100ths of a second, so 11:59:59.999 will get rounded up to 12:00:00.000.
You basically have three choices:
1) BETWEEN CAST('01/01/2008 00:00:00.000' AS DATETIME) AND CAST('03/31/2008 12:59:59.997' AS DATETIME)
2) YEAR(my_date) = 2008 AND MONTH(my_date) BETWEEN 1 AND 3
3) my_date >= CAST('01/01/2008 00:00:00.000' AS DATETIME) AND my_date < CAST('04/01/2008 00:00:00.000' AS DATETIME)
The first method isn't very intuitive and is error-prone in my opinion. The second method kills performance since indexes can't be used and it becomes much more complex if you can have searches that span years or begin/end in the middle of months. The third method, which Rowland suggested, is the best I think.
Simply try removing the time from the date field like so:
declare #startDate varchar(20)
declare #endDate varchar(20)
set #startDate = '01/01/2008'
set #endDate = '04/01/2008'
SELECT min(date),max(date) FROM view_Inspections
WHERE CAST(FLOOR(CAST(date AS FLOAT)) AS DATETIME) BETWEEN CAST(#startDate AS DATETIME) And CAST(#startDate AS DATETIME))
This will return everything from 01/01/2008 00:00:00 to 04/01/2008 11:59:59.999.
If you don't want 04/01 included, change your end date to 03/31/2008.
Your best solution is just create a BIGINT(10) field that called "julian", and store it in YYYYMMDD.
Then do the query
where julian >= '20120103' AND julian <= '20120203'