Attempting DateTime conversion - sql

I have a column as per below in datetime format and this column is defined as nvarchar(max) datatype as I loaded it from an Excel file.
I need to convert it to datetime datatype - if someone can please help to do it. Thanks
ReportDateTime
-------------------
11/01/2019 08:27:00
25/01/2019 11:48:00
I tried to load different way but did not succeed.

One option is Set DateFormat DMY prior to the load from excel
Example
Set Dateformat DMY
Declare #YourTable Table ([ReportDateTime] Datetime)
Insert Into #YourTable Values
('11/01/2019 08:27:00')
,('25/01/2019 11:48:00')
Select *
from #YourTable
Results
ReportDateTime
2019-01-11 08:27:00.000
2019-01-25 11:48:00.000
EDIT - Or if data loaded as a string
Declare #YourTable Table ([ReportDateTime] varchar(50))
Insert Into #YourTable Values
('11/01/2019 08:27:00')
,('25/01/2019 11:48:00')
Select *
,AsDateTime = try_convert(datetime, [ReportDateTime],103)
from #YourTable
Results
ReportDateTime AsDateTime
11/01/2019 08:27:00 2019-01-11 08:27:00.000
25/01/2019 11:48:00 2019-01-25 11:48:00.000

Related

Convert particular string to last day of month

I've got a dataset in SQL Server and I need to transform one of the columns.
The string (nvarchar(max)) is a combination of the year and week of year, so the 8th week of 2021 looks like 202108, the 32nd week of 2019 looks like 201932, and so on.
What I need is to convert this into the last day of the month of the given week, so for 202302, I need 01/31/2023, in datetime format. I've tried a few different methods like CAST() to no avail.
Perhaps this will help, but it really depends on how you count weeks. Perhaps a calendar table would be a better option.
Declare #YourTable Table ([SomeCol] varchar(50)) Insert Into #YourTable Values
(202108)
,(201932)
,(202302)
Select *
,NewVal = EOMonth(dateadd(week,try_convert(int,right(SomeCol,2)),convert(date,left(SomeCol,4)+'0101')))
from #YourTable
Results
SomeCol NewVal
202108 2021-02-28
201932 2019-08-31
202302 2023-01-31
in datetime format
Once more for those in back: datetime values do not have a human-readable format. Anything you see indicating otherwise is a convenience provided by the tooling.
Your goal at the database level should be to return a basic datetime value, and let the client code worry about the formatting. But we can do that:
EOMonth(DATEADD(week, cast(right([MyColumn],2) as int),CONVERT(datetime, left([MyColumn], 4) + '0101')))
Of course, the main key here is the EOMonth() function. Everything else is just string parsing
data Thanks John Cappelletti
Declare #YourTable Table ([SomeCol] varchar(50));
Insert Into #YourTable
([SomeCol]) Values
('202108')
,('201932')
,('202302');
query
SELECT
DATEADD(wk,cast(right([SomeCol],2) as int),DATEADD(yy,cast((left([SomeCol],4)) as int)-1900,0))-1 AS WeekEnd
from #YourTable
dbfiddle

How do I stop SQL Server swapping the month and day?

I have the following query:
DECLARE #someDateTime DATETIME = '2019-12-01 00:00:00.000'; -- 1st December 2019
SELECT #someDateTime;
Result
2019-01-12 00:00:00.000
I expected the result to be 2019-12-01 00:00:00.000 (1st December 2019) - The month and the date swap for some unknown reason.
Until recently, I never had an issue with this format.
How do I enter the date in the format "YYYY-MM-DD HH:mm:ss.000", and have it maintain that format once assigned to a variable/displayed in a select?
What setting determines this format that may have changed?
Potentialy useful information
dbcc useroptions
Result:
Set Option | Value
---------- -----
...
language | British
dateformat | dmy
...
Things I tried:
Query 1
Chaning the date to something that would be invalid if swapped
DECLARE #someDateTime DATETIME = '2019-12-20 00:00:00.000';
SELECT #someDateTime;
Result:
Msg 242, Level 16, State 3, Line 4
The conversion of a varchar data type to a datetime data type resulted in an out-of-range value.
Query 2
Setting the variable after it's been declared
DECLARE #someDateTime DATETIME;
SET #someDateTime = '2019-12-01 00:00:00.000';
SELECT #someDateTime;
Result - UNDESIRED:
2019-01-12 00:00:00.000
Query 3
Inserting the variable into a table variable
DECLARE #someDateTime DATETIME = '2019-12-01 00:00:00.000';
DECLARE #someTable TABLE (someDateTimeColumn DATETIME);
INSERT #someTable VALUES (#someDateTime);
SELECT * FROM #someTable
Result - UNDESIRED:
someDateTimeColumn
------------------
2019-01-12 00:00:00.000
Query 4
Inserting the data directly into a table variable
DECLARE #someTable TABLE (someDateTimeColumn DATETIME);
INSERT #someTable VALUES ('2019-12-01 00:00:00.000');
SELECT * FROM #someTable
Result: UNDESIRED
someDateTimeColumn
------------------
2019-01-12 00:00:00.000
Query 5
Changing the format of the entered string
DECLARE #someDateTime DATETIME = '01/12/2019';
SELECT #someDateTime;
Result - DESIRED
2019-12-01 00:00:00.000
Query 6
Changing the format of the entered string
DECLARE #someDateTime DATETIME = '2019-12-01T00:00:00.00';
SELECT #someDateTime;
Result - DESIRED:
2019-12-01 00:00:00.000
Query 7
Changing the format of the entered string
DECLARE #someDateTime DATETIME = '2019-12-01';
SELECT #someDateTime;
Result - UNDESIRED:
2019-01-12 00:00:00.000
Query 8
Using SET DATEFORMAT
SET DATEFORMAT ymd
DECLARE #someDateTime DATETIME = '2019-12-01';
SELECT #someDateTime;
Result - DESIRED
2019-12-01 00:00:00.000
You may use the literal format YYYYMMDD which is always intepreted as year-month-day, regardless of the locale settings of your SQL Server:
DECLARE #someDateTime DATETIME = '20191201 00:00:00.000';
One solution is to use the full ISO8601 format, ie 2019-12-01T00:00:00.000, another to use the unseparated date format, ie 20191201 00:00:00.000. A better solution though would be to switch to datetime2.
datetime2 was introduced 15 (or was it 11) years ago to get rid of datetime's quirks, like the millisecond inaccuracy, arbitrary precision, weird arithmetic and ... parsing idiosyncrasies. For example, datetime2's parsing of the ISO8601 format isn't affected by DATEFORMAT :
SET DATEFORMAT ydm
DECLARE #someDateTime DATETIME2(0) = '2019-12-01 00:00:00.000'
select #someDateTime
------
2019-12-01 00:00:00
This secures your code from unfortunate server setting modifications
After reading this article from #SMor's comment, a comment my colleague made from a google search, and remembering something I did a few months ago, I think I've worked out what's happening and what's changed.
My db user was, by default, set to:
language | us_english
dateformat | mdy
So when reading the string '2019-12-01' SQL Server was expecting mm-dd-yyyy.
SQL server is clever though. It sees the first part 2019 and realises that it's actually the year, so it shifts the year to the end, then tries again.*
It now has 12-01-2019 which matches the format it's expecting.
When you open your account properties in SSMS, the language drop down defaults to the first language in the list (Arabic).
I happend to be in there a few months ago for something unrelated and decided, to make sure I didn't accidently set it to Arabic, I'd change that as well.
I chose British.
My db user is now set to:
language | British
dateformat | dmy
So when reading the string '2019-12-01' SQL Server is expecting dd-mm-yyyy.
Once it's shifted the year, it becomes 12-01-2019 which it interprets as dd-mm-yyyy thus leaving me with January 12th 2019 instead of December 1st 2019
Today has been a long day.
*Please note this is a rather simplified explanation of how I understand this issue. This may not be how it actually functions in reality but works to satisfy my curiosity on this issue.

I need to convert this string to datetime in SQL Server

String:
'01/04/2019 01:50:31.230000000'
Expected result:
01/04/2019 01:50:31.230
as a DATETIME.
Query used:
SELECT CONVERT(DATETIME, '01/04/2019 01:50:31.230000000', 113)
Converting that string, which is in the 103 format, would work if it didn't have the last 6 zero's.
So a SUBSTRING or LEFT could be used to keep only 23 characters.
And then convert it to a DATETIME.
But that string, can be converted just fine to a DATETIME2.
Since a DATETIME2 is more accurate.
And a DATETIME2 can be simply casted or converted to a DATETIME.
Note that DATETIME isn't stored with a format in the table.
The way it's displayed is a setting.
However, you can FORMAT a DATETIME back to a string in the specific format you need. (starting with SQL Server 2012)
Example snippet:
select
col as col_input_string,
CAST(CONVERT(datetime2, col, 103) AS datetime) as col_as_datetime,
FORMAT(CONVERT(datetime2, col, 103), 'dd/MM/yyyy HH:mm:ss.fff') as col_as_formatted_string
from (values
('01/04/2019 01:50:31.230000000')
,('31/12/2018 13:33:44.123456789')
) q(col);
Result:
col_input_string col_as_datetime col_as_formatted_string
01/04/2019 01:50:31.230000000 2019-04-01 01:50:31.230 01/04/2019 01:50:31.230
31/12/2018 13:33:44.123456789 2018-12-31 13:33:44.123 31/12/2018 13:33:44.123
The code you want is:
SELECT CONVERT(datetime,LEFT('01/04/2019 01:50:31.230000000',23),103);
You need to use LEFT as datetime is only accurate to 1/300 of a second; thus you need to trim off the accuracy that can't be used.
Try to use
declare #vardate varchar(50) = '01/04/2019 01:50:31.230000000'
declare #date datetime =convert(date, left(#vardate,23), 103)
declare #time time = convert(time, substring(#vardate,12,12), 14)
select DATEADD(DAY, DATEDIFF(DAY, #time, #date), CAST(#time AS DATETIME)) AS Result
if that does not work check different convert formats.

SQL Server 2014 insert/update smalldatetime value with seconds

I'm having a strange issue with the smalldatetime data type in SQL Server.
I have a very basic table
create table datetest (
value smalldatetime not null
)
And when I run the following
insert into datetest
values ('2016-12-29 21:30:00');
I see the value is 2016-12-29 21:30:00
Then when I run the following
update datetest
set value = '2016-12-29 21:31:30'
I see the value is 2016-12-29 21:31:00
It did not include the seconds. Why is this?
This is happening because precision of smalldatetime is 1 minute. It discards any seconds in datetime value by rounding off. For e.g:
'2014-10-10 12:13:29' is rounded off to '2014-10-10 12:13:00' and '2014-10-10 12:13:30' is rounded off to '2014-10-10 12:14:00'
This is one of the characteristics of smalldatetime over datetime.
Microsoft documentation on smalldatetime
The main differentation is that it rounds to the nearest minute. If you want to see seconds (and milliseconds) then you need to consider the datetime data type.
In your example however, it should return the value 2016-12-29 21:32:00 because it rounds up from 30 seconds to the next minute. anything less than 30 seconds gets rounded down. Example;
CREATE TABLE #DateTest (ID int, DateValue smalldatetime)
INSERT INTO #DateTest (ID, DateValue)
VALUES
(1,'2016-12-29 21:31:29')
,(2,'2016-12-29 21:31:30')
SELECT * FROM #DateTest
Output
ID DateValue
1 2016-12-29 21:31:00
2 2016-12-29 21:32:00
Some further reading links;
http://blog.sqlauthority.com/2010/06/01/sql-server-precision-of-smalldatetime-a-1-minute-precision/
http://sqlcoach.blogspot.co.uk/2007/08/sql-server-storing-time-coming-soon.html
http://sqlhints.com/2016/10/10/difference-between-smalldatetime-and-datetime-data-types-in-sql-server/
When the conversion is to datetime, the smalldatetime value is copied to the datetime value. The fractional seconds will make next nearest minutes. The following code shows the results of converting a smalldatetime value to a datetime value.
DECLARE #smalldatetime smalldatetime = '1955-12-13 12:43:10';
DECLARE #datetime datetime = #smalldatetime;
SELECT #smalldatetime AS '#smalldatetime', #datetime AS 'datetime';
--Result
--#smalldatetime datetime
------------------------- -----------------------
--1955-12-13 12:43:00 1955-12-13 12:43:00.000
Take a look MSDN Link
It rounds all seconds to minutes:
Time range:
00:00:00 through 23:59:59
2007-05-09 23:59:59 will round to
2007-05-10 00:00:00
see chapter smalldatetime Description: https://msdn.microsoft.com/en-us/library/ms182418(v=sql.120).aspx

Sql Convert Text Field To Date Field

I'm importing an access database to sql.
The original access database has a date field that imports nicely, but the time field is text (10:00 AM, for instance).
I have over 4000 records and assume there is a way to convert 10:00 AM to 10:00:00.000 (or 07:30 PM to 19:30:00.000, etc...) so that it can be combined with the pre-existing date field (which is now like 2011-11-11 00:00:00.000).
Also, if it's easy to do the conversion and concatenation in the same process, please note.
to convert the time from am or pm 10:00 PM format into time format 10:00:00.000:
select cast(timestring as time(7))
look this:
declare #timeField as varchar(10)
set #timeField = '07:30 PM'
declare #dateField as varchar(10)
set #dateField = '1900-01-01'
select CONVERT(datetime,#dateField + ' ' + CAST(CONVERT(time, #timeField ,121) AS VARCHAR(11)),121)
In your import scripts (I assume you use some sort of SQL to E.T.L your data from Access to SQL server), you can use the convert function as such:
declare #t as time = Convert(time, '10:00PM' )
print #t -- prints 22:00:00.0000000
OR
declare #t as time = Convert(time, '10:00AM' )
print #t -- prints 10:00:00.0000000
And of course if you want to control the precision as per your example:
Convert(time(3), '10:00PM' ) -- prints 22:00:00.000