TSQL Datediff from a string - sql-server

I have a simple query that I am trying to use this select statement on.
I am trying to get the difference in seconds from the date provided (a UNIX timestamp).
select
DATEDIFF(s, '19700101', CAST(CAST('2014-08-27 08:59:56.0000000' AS DATETIME) AS INT))
When I try this, I get the following error :
Conversion failed when converting date and or time from character string.
I figured casting the string as datetime would have resolved that?

First of all, you should try to avoid using shorthands for the datepart, instead of s, use SECOND.
Another good practice when casting a string to a date is to use CONVERT so you can specify the format to use on the conversion (in your case, it would be 121. Finally, for the whole thing to work, you'll need to use less miliseconds (up to 3):
DECLARE #Date VARCHAR(50)
SET #Date = '2014-08-27 08:59:56.0000000'
SELECT DATEDIFF(SECOND,'19700101',CONVERT(DATETIME,LEFT(#Date,23),121))

Related

SQL Server date separator dot not working while inserting data

When I insert a date like this '01.03.2020 21:35:12' it changes into '2020-01-03 21:35:12.000'.
I want to insert the date with DOT as the Date separator.
NOTE: I'm not using a stored procedure, just insert query.
This is an inferior choice in format, because nobody reading that code can be certain whether you meant January 3rd or March 1st. You can get there this way, but it is ugly, unintuitive, and equally non-self-documenting:
DECLARE #d varchar(30) = '01.03.2020 21:35:12';
SELECT CONVERT(datetime, #d, 104);
Much better to use a standard, unambiguous date format for literals. These are the only two formats not subject to misinterpretation by language, dateformat, or regional settings, and therefore don't need to be accompanied by cryptic style numbers:
DECLARE #d1 varchar(30) = '20200301 21:35:12',
#d2 varchar(30) = '2020-03-01T21:35:12';
SELECT CONVERT(datetime, #d1), CONVERT(datetime, #d2);
Background:
Recommended SQL Server Date Formats
Bad Habits to Kick : Mis-handling date / range queries
Dating Responsibly
I don't think you can change the display in SSMS from the YYYY-MM-DD TIME format. If you want to change the way you get the date back when selected, you can use the CONVERT or FORMAT functions.
CONVERT function: https://www.mssqltips.com/sqlservertip/1145/date-and-time-conversions-using-sql-server/
FORMAT function: https://learn.microsoft.com/en-us/sql/t-sql/functions/format-transact-sql
You may need to select your datetime twice with the CONVERT. Once for the date and once for the time in order to get the combination of formats you want.
-John

How to add an hour in timestamp in sql server (without Declare)

I want to add an hour in the parameter TimeStamp, but not with declare parameter i.e
DECLARE #datetime2 datetime2 = '2019-03-01T09:25:21.1+01:00'
SELECT DATEADD(hour,1,#datetime)
I have a column name TimeStamp in a table and i want to add in all data plus 1 hour.
The column
TimeStamp
2019-03-01T09:25:20.1+01:00
2019-03-01T09:25:21.1+01:00
2019-03-01T09:25:19.1+01:00
I try something like this
SELECT DATEADD(hour,1, TimeStamp), but i have an error
Conversion failed when converting date and/or time from character
string.
Any possible answers ??
Thanks
SELECT DATEADD(hour,1, TimeStamp) is correct
However, The format in TimeStamp is wrong,
So, cast it to DateTime2 First
CAST(TimeStamp as DateTime2)
OR
CAST('2019-03-01T09:25:20.1+01:00' as DateTime2)
So,
SELECT DATEADD(hour, 1, CAST(TimeStamp as DateTime2))
Conversion failed when converting date and/or time from character
string.
The error message means that column TimeStamp stored as a string. DATEADD expects a valid value that is date/datetime/datetime2 or can be converted into it from a string. Because a sample value look like DATETIME2, such extra conversion perhaps is needed:
SELECT DATEADD(hour,1, CAST(TimeStamp as datetime2))
Your syntax will be fine as defined.
It might be a value in your column that is not able to parse to datetime2 because it contains an invalid character.
You could add the ISDATE() to the expression to check if it is valid.
https://learn.microsoft.com/en-us/sql/t-sql/functions/isdate-transact-sql?view=sql-server-2017
edit: forgot to mention you could parse before adding with try_cast or try_convert to datetime2
In Your Timestamp +01:00 represents the Time offset to GMT. You can convert this to your local time and then Add the Hours using DATEADD()
or Remove the Time Offset from the string and add one hour using DATEADD() As suggested by Others.
According to this https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-2017#date-and-time-styles
you have to convert the timestamp with timezone using type 127.
127 is the input format for:
ISO8601 with time zone Z.
yyyy-mm-ddThh:mi:ss.mmmZ (no spaces)
Note: For a milliseconds (mmm) value of 0, the millisecond decimal value will not display. For example, the value '2012-11-07T18:26:20.000 will display as '2012-11-07T18:26:20'.
select convert(datetime2, '2019-03-01T09:25:20.1+01:00', 127)
if you are not using convert and the 127 by using cast you may run in conversion problems depending on language settings of the users.
Maybe you are after this?
select dateadd(hour,1,convert(datetimeoffset, TimeStamp))
Best to not store dates and times as text though.
Edit: Note that his will retain your time zone information if that is important to you.

Convert Time zonoffset value to varchar

Query:
DECLARE #TimeZoneOffset datetimeoffset
SELECT #TimeZoneOffset = Time_Zone_Offset
FROM OFFSET_TABLE WHERE Active=1
Time_Zone_Offset column contains value like -6:00 (only offset)
When I do SELECT #TimeZoneOffset it throws me an error
Conversion failed when converting date and/or time from character string.
I know I am doing something wrong. I may need to CONVERT/CAST but can't get o/p so far.
Any help
To visualize what is happening here, try this:
DECLARE #x VARCHAR;
SET #x = 'abcdefghijklmnop';
SELECT #x;
Result:
----------
a
You have silently lost data from your variable, because you didn't bother declaring a length for your VARCHAR. In your case, I think you are ending up trying to use the string - somewhere, as opposed to the string -6:00.
I'm not sure how a simple SELECT yielded the error you mentioned; I suspect you are using it in some other context you haven't shown. But please try it again once your variable has been declared correctly.
Now I see why, your question wasn't correct - you said you were converting to VARCHAR but you weren't. This is not really unexpected, as -6:00 is not a valid DATETIMEOFFSET value; there is expected to be date and time components as well, otherwise the data type would just be called OFFSET. A valid DATETIMEOFFSET, according to the documentation, is:
DECLARE #d DATETIMEOFFSET = '1998-09-20 7:45:50.71345 -05:00';
So perhaps you have some datetime value and you want to apply the offset, well you can use SWITCHOFFSET() for that. However -6:00 is not a valid value; it needs to be in [+/-]hh:mm format (notice the leading 0 above, which seems to be missing from your sample data). So this would be valid:
DECLARE #datetime DATETIME = GETDATE(), #offset VARCHAR(6) = '-06:00';
SELECT SWITCHOFFSET(#datetime, #offset);
You need to correct the data in your offsets table and you need to change the way you are using the output. Personally, I've found it easier to stay away from DATETIMEOFFSET and SWITCHOFFSET(), especially since they are not DST-aware. I've had much better luck using a calendar table for offsets, storing the offsets in minutes, and using DATEADD to switch between time zones. YMMV.

How to convert SQL Server's timestamp column to datetime format

As SQL Server returns timestamp like 'Nov 14 2011 03:12:12:947PM', is there some easy way to convert string to date format like 'Y-m-d H:i:s'.
So far I use
date('Y-m-d H:i:s',strtotime('Nov 14 2011 03:12:12:947PM'))
SQL Server's TIMESTAMP datatype has nothing to do with a date and time!
It's just a hexadecimal representation of a consecutive 8 byte integer - it's only good for making sure a row hasn't change since it's been read.
You can read off the hexadecimal integer or if you want a BIGINT. As an example:
SELECT CAST (0x0000000017E30D64 AS BIGINT)
The result is
400756068
In newer versions of SQL Server, it's being called RowVersion - since that's really what it is. See the MSDN docs on ROWVERSION:
Is a data type that exposes automatically generated, unique binary numbers within a database. rowversion is generally used as a mechanism
for version-stamping table rows. The
rowversion data type is just an incrementing number and does not
preserve a date or a time. To record a date or time, use a datetime2
data type.
So you cannot convert a SQL Server TIMESTAMP to a date/time - it's just not a date/time.
But if you're saying timestamp but really you mean a DATETIME column - then you can use any of those valid date formats described in the CAST and CONVERT topic in the MSDN help. Those are defined and supported "out of the box" by SQL Server. Anything else is not supported, e.g. you have to do a lot of manual casting and concatenating (not recommended).
The format you're looking for looks a bit like the ODBC canonical (style = 121):
DECLARE #today DATETIME = SYSDATETIME()
SELECT CONVERT(VARCHAR(50), #today, 121)
gives:
2011-11-14 10:29:00.470
SQL Server 2012 will finally have a FORMAT function to do custom formatting......
The simplest way of doing this is:
SELECT id,name,FROM_UNIXTIME(registration_date) FROM `tbl_registration`;
This gives the date column atleast in a readable format.
Further if you want to change te format click here.
Using cast you can get date from a timestamp field:
SELECT CAST(timestamp_field AS DATE) FROM tbl_name
Works fine, except this message:
Implicit conversion from data type varchar to timestamp is not allowed. Use the CONVERT function to run this query
So yes, TIMESTAMP (RowVersion) is NOT a DATE :)
To be honest, I fidddled around quite some time myself to find a way to convert it to a date.
Best way is to convert it to INT and compare. That's what this type is meant to be.
If you want a date - just add a Datetime column and live happily ever after :)
cheers mac
My coworkers helped me with this:
select CONVERT(VARCHAR(10), <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(VARCHAR(10), <tms_column>, 112);
or
select CONVERT(DATE, <tms_column>, 112), count(*)
from table where <tms_column> > '2012-09-10'
group by CONVERT(DATE, <tms_column>, 112);
"You keep using that word. I do not think it means what you think it means."
— Inigo Montoya
The timestamp has absolutely no relationship to time as marc_s originally said.
declare #Test table (
TestId int identity(1,1) primary key clustered
,Ts timestamp
,CurrentDt datetime default getdate()
,Something varchar(max)
)
insert into #Test (Something)
select name from sys.tables
waitfor delay '00:00:10'
insert into #Test (Something)
select name from sys.tables
select * from #Test
Notice in the output that Ts (hex) increments by one for each record, but the actual time has a gap of 10 seconds. If it were related to time then there would be a gap in the timestamp to correspond with the difference in the time.
for me works:
TO_DATE('19700101', 'yyyymmdd') + (TIME / 24 / 60 / 60)
(oracle DB)
Robert Mauro has the correct comment. For those who know the Sybase origins, datetime was really two separate integers, one for date, one for time, so timestamp aka rowversion could just be considered the raw value captured from the server. Much faster.
After impelemtation of conversion to integer
CONVERT(BIGINT, [timestamp]) as Timestamp
I've got the result like
446701117
446701118
446701119
446701120
446701121
446701122
446701123
446701124
446701125
446701126
Yes, this is not a date and time, It's serial numbers
Why not try FROM_UNIXTIME(unix_timestamp, format)?
I had the same problem with timestamp eg:'29-JUL-20 04.46.42.000000000 PM'. I wanted to turn it into 'yyyy-MM-dd' format. The solution that finally works for me is
SELECT TO_CHAR(mytimestamp, 'YYYY-MM-DD') FROM mytable;
I will assume that you've done a data dump as insert statements, and you (or whoever Googles this) are attempting to figure out the date and time, or translate it for use elsewhere (eg: to convert to MySQL inserts). This is actually easy in any programming language.
Let's work with this:
CAST(0x0000A61300B1F1EB AS DateTime)
This Hex representation is actually two separate data elements... Date and Time. The first four bytes are date, the second four bytes are time.
The date is 0x0000A613
The time is 0x00B1F1EB
Convert both of the segments to integers using the programming language of your choice (it's a direct hex to integer conversion, which is supported in every modern programming language, so, I will not waste space with code that may or may not be the programming language you're working in).
The date of 0x0000A613 becomes 42515
The time of 0x00B1F1EB becomes 11661803
Now, what to do with those integers:
Date
Date is since 01/01/1900, and is represented as days. So, add 42,515 days to 01/01/1900, and your result is 05/27/2016.
Time
Time is a little more complex. Take that INT and do the following to get your time in microseconds since midnight (pseudocode):
TimeINT=Hex2Int(HexTime)
MicrosecondsTime = TimeINT*10000/3
From there, use your language's favorite function calls to translate microseconds (38872676666.7 µs in the example above) into time.
The result would be 10:47:52.677
Some of them actually does covert to a date-time from SQL Server 2008 onwards.
Try the following SQL query and you will see for yourself:
SELECT CAST (0x00009CEF00A25634 AS datetime)
The above will result in 2009-12-30 09:51:03:000 but I have encountered ones that actually don't map to a date-time.
Not sure if I'm missing something here but can't you just convert the timestamp like this:
CONVERT(VARCHAR,CAST(ZEIT AS DATETIME), 110)

Sql Server string to date conversion

I want to convert a string like this:
'10/15/2008 10:06:32 PM'
into the equivalent DATETIME value in Sql Server.
In Oracle, I would say this:
TO_DATE('10/15/2008 10:06:32 PM','MM/DD/YYYY HH:MI:SS AM')
This question implies that I must parse the string into one of the standard formats, and then convert using one of those codes. That seems ludicrous for such a mundane operation. Is there an easier way?
Try this
Cast('7/7/2011' as datetime)
and
Convert(DATETIME, '7/7/2011', 101)
See CAST and CONVERT (Transact-SQL) for more details.
Run this through your query processor. It formats dates and/or times like so and one of these should give you what you're looking for. It wont be hard to adapt:
Declare #d datetime
select #d = getdate()
select #d as OriginalDate,
convert(varchar,#d,100) as ConvertedDate,
100 as FormatValue,
'mon dd yyyy hh:miAM (or PM)' as OutputFormat
union all
select #d,convert(varchar,#d,101),101,'mm/dd/yy'
union all
select #d,convert(varchar,#d,102),102,'yy.mm.dd'
union all
select #d,convert(varchar,#d,103),103,'dd/mm/yy'
union all
select #d,convert(varchar,#d,104),104,'dd.mm.yy'
union all
select #d,convert(varchar,#d,105),105,'dd-mm-yy'
union all
select #d,convert(varchar,#d,106),106,'dd mon yy'
union all
select #d,convert(varchar,#d,107),107,'Mon dd, yy'
union all
select #d,convert(varchar,#d,108),108,'hh:mm:ss'
union all
select #d,convert(varchar,#d,109),109,'mon dd yyyy hh:mi:ss:mmmAM (or PM)'
union all
select #d,convert(varchar,#d,110),110,'mm-dd-yy'
union all
select #d,convert(varchar,#d,111),111,'yy/mm/dd'
union all
select #d,convert(varchar,#d,12),12,'yymmdd'
union all
select #d,convert(varchar,#d,112),112,'yyyymmdd'
union all
select #d,convert(varchar,#d,113),113,'dd mon yyyy hh:mm:ss:mmm(24h)'
union all
select #d,convert(varchar,#d,114),114,'hh:mi:ss:mmm(24h)'
union all
select #d,convert(varchar,#d,120),120,'yyyy-mm-dd hh:mi:ss(24h)'
union all
select #d,convert(varchar,#d,121),121,'yyyy-mm-dd hh:mi:ss.mmm(24h)'
union all
select #d,convert(varchar,#d,126),126,'yyyy-mm-dd Thh:mm:ss:mmm(no spaces)'
In SQL Server Denali, you will be able to do something that approaches what you're looking for. But you still can't just pass any arbitrarily defined wacky date string and expect SQL Server to accommodate. Here is one example using something you posted in your own answer. The FORMAT() function and can also accept locales as an optional argument - it is based on .Net's format, so most if not all of the token formats you'd expect to see will be there.
DECLARE #d DATETIME = '2008-10-13 18:45:19';
-- returns Oct-13/2008 18:45:19:
SELECT FORMAT(#d, N'MMM-dd/yyyy HH:mm:ss');
-- returns NULL if the conversion fails:
SELECT TRY_PARSE(FORMAT(#d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);
-- returns an error if the conversion fails:
SELECT PARSE(FORMAT(#d, N'MMM-dd/yyyy HH:mm:ss') AS DATETIME);
I strongly encourage you to take more control and sanitize your date inputs. The days of letting people type dates using whatever format they want into a freetext form field should be way behind us by now. If someone enters 8/9/2011 is that August 9th or September 8th? If you make them pick a date on a calendar control, then the app can control the format. No matter how much you try to predict your users' behavior, they'll always figure out a dumber way to enter a date that you didn't plan for.
Until Denali, though, I think that #Ovidiu has the best advice so far... this can be made fairly trivial by implementing your own CLR function. Then you can write a case/switch for as many wacky non-standard formats as you want.
UPDATE for #dhergert:
SELECT TRY_PARSE('10/15/2008 10:06:32 PM' AS DATETIME USING 'en-us');
SELECT TRY_PARSE('15/10/2008 10:06:32 PM' AS DATETIME USING 'en-gb');
Results:
2008-10-15 22:06:32.000
2008-10-15 22:06:32.000
You still need to have that other crucial piece of information first. You can't use native T-SQL to determine whether 6/9/2012 is June 9th or September 6th.
SQL Server (2005, 2000, 7.0) does not have any flexible, or even non-flexible, way of taking an arbitrarily structured datetime in string format and converting it to the datetime data type.
By "arbitrarily", I mean "a form that the person who wrote it, though perhaps not you or I or someone on the other side of the planet, would consider to be intuitive and completely obvious." Frankly, I'm not sure there is any such algorithm.
Use this:
SELECT convert(datetime, '2018-10-25 20:44:11.500', 121) -- yyyy-mm-dd hh:mm:ss.mmm
And refer to the table in the official documentation for the conversion codes.
For this problem the best solution I use is to have a CLR function in Sql Server 2005 that uses one of DateTime.Parse or ParseExact function to return the DateTime value with a specified format.
Short answer:
SELECT convert(date, '10/15/2011 00:00:00', 101) as [MM/dd/YYYY]
Other date formats can be found at SQL Server Helper > SQL Server Date Formats
Took me a minute to figure this out so here it is in case it might help someone:
In SQL Server 2012 and better you can use this function:
SELECT DATEFROMPARTS(2013, 8, 19);
Here's how I ended up extracting the parts of the date to put into this function:
select
DATEFROMPARTS(right(cms.projectedInstallDate,4),left(cms.ProjectedInstallDate,2),right( left(cms.ProjectedInstallDate,5),2)) as 'dateFromParts'
from MyTable
The most upvoted answer here are guravg's and Taptronic's. However, there's one contribution I'd like to make.
The specific format number they showed from 0 to 131 may vary depending on your use-case (see full number list here), the input number can be a nondeterministic one, which means that the expected result date isn't consistent from one SQL SERVER INSTANCE to another, avoid using the cast a string approach for the same reason.
Starting with SQL Server 2005 and its compatibility level of 90,
implicit date conversions became nondeterministic. Date conversions
became dependent on SET LANGUAGE and SET DATEFORMAT starting with
level 90.
Non deterministic values are 0-100, 106, 107, 109, 113, 130. which may result in errors.
The best option is to stick to a deterministic setting, my current preference are ISO formats (12, 112, 23, 126), as they seem to be the most standard for IT people use cases.
Convert(varchar(30), '210510', 12) -- yymmdd
Convert(varchar(30), '20210510', 112) -- yyyymmdd
Convert(varchar(30), '2021-05-10', 23) -- yyyy-mm-dd
Convert(varchar(30), '2021-05-10T17:01:33.777', 126) -- yyyy-mm-ddThh:mi:ss.mmm (no spaces)
This page has some references for all of the specified datetime conversions available to the CONVERT function. If your values don't fall into one of the acceptable patterns, then I think the best thing is to go the ParseExact route.
Personally if your dealing with arbitrary or totally off the wall formats, provided you know what they are ahead of time or are going to be then simply use regexp to pull the sections of the date you want and form a valid date/datetime component.
If you want SQL Server to try and figure it out, just use CAST
CAST('whatever' AS datetime)
However that is a bad idea in general. There are issues with international dates that would come up. So as you've found, to avoid those issues, you want to use the ODBC canonical format of the date. That is format number 120, 20 is the format for just two digit years.
I don't think SQL Server has a built-in function that allows you to provide a user given format. You can write your own and might even find one if you search online.
convert string to datetime in MSSQL implicitly
create table tmp
(
ENTRYDATETIME datetime
);
insert into tmp (ENTRYDATETIME) values (getdate());
insert into tmp (ENTRYDATETIME) values ('20190101'); --convert string 'yyyymmdd' to datetime
select * from tmp where ENTRYDATETIME > '20190925' --yyyymmdd
select * from tmp where ENTRYDATETIME > '20190925 12:11:09.555'--yyyymmdd HH:MIN:SS:MS
You can easily achieve this by using this code.
SELECT Convert(datetime, Convert(varchar(30),'10/15/2008 10:06:32 PM',102),102)
This code solve my problem :
convert(date,YOUR_DATE,104)
If you are using timestamp you can you the below code :
convert(datetime,YOUR_DATE,104)
dateadd(day,0,'10/15/2008 10:06:32 PM')

Resources