Convert particular string to last day of month - sql

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

Related

Explicit conversion from data type date to bigint is not allowed

This used to work with a column type of DATEIME but now it won't with DATE.
CONVERT(BIGINT,ev.StartDate) * -1
Is there anyway to get a BIGINT value from a DATE column?
You can cast the startdate as datetime for conversion.
CONVERT(BIGINT,CAST(ev.StartDate as DATETIME)) * -1
Yet another option. This will even flip the sign for you
Example
Declare #YourTable table (StartDate date)
Insert Into #YourTable values ('2017-05-30')
Select DateDiff(DAY,StartDate,-1)
From #YourTable
Returns
-42884
First, dates in SQL Server are counted by days from the year 1900. A big int starts to be useful at about 2.1 billion. That corresponds to a year in the range of 5.8 million. Do you really have dates that large?
Of course, casting to an int is not permitted. You can cast datetime values . . . but are there other ways?
One simple way is:
select 1 + datediff(day, 0, datecol)
The "+ 1" is needed so the value matches the actual conversion. (You can use "-1" instead of "0" instead.)
Or, perhaps you want Unix time in seconds or milliseconds. For that:
select datediff_big(ms, '1970-01-01', datecol)
You might require to convert to varchar and then bigint
select Convert(bigint,convert(varchar(10),ev.StartDate,112))*(-1)

Date is string between hyphens in SQL Server

I have date formats that are as follows:
Date_str
19-12-2007
31-7-2009
3-1-2010
31-11-2009
etc.
I can't do the following:
CONCAT(RIGHT(Date_str,4),SUBSTRING(Date_str,3,3),LEFT(2))
because as you can see above, the dates are not the same length. Is there a way in SQL Server to extract the date as datetime/date?
I also tried
Convert(datetime, Date_str)
but it just threw an error:
The conversion of a varchar data type to a datetime data type resulted
in an out-of-range value.
If 2012+, I would use Try_Convert(). This will return bogus dates as NULL.
Example
Declare #YourTable Table ([Date_str] varchar(50))
Insert Into #YourTable Values
('19-12-2007')
,('31-7-2009')
,('3-1-2010')
,('31-11-2009')
Select *
,try_convert(date,Date_Str,105)
from #YourTable
Returns
Date_str (No column name)
19-12-2007 2007-12-19
31-7-2009 2009-07-31
3-1-2010 2010-01-03
31-11-2009 NULL -- Notice 11/31 is NOT a date
See https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql for date formats
You probably need
CONVERT(DateTime, Date_str, 105)
As I mentioned in the comments, the only realistic solution is to convert that string into a proper date-typed column. The current format doesn't allow date sorting, or search for a range of dates, eg to find entries in the last week, or between one date and the other.
Parsing with CONVERT or TRY_PARSE means that no indexes can be used to speed up queries. Each time :
WHERE CONVERT(Date, Date_str, 105) > '20170101'
is used, the server will have to scan the entire table to convert the data, then filter the rows.
If you can't change the type of the field itself, you can create a persisted computed column that returns the value as a date and add indexes to it. You'll be able to use that column for indexed querying:
alter table SomeTable add date2 as TRY_convert(Actual_Date,date_str,105) PERSISTED
create index IX_SomeTable_ActualDate on SomeTable (Actual_Date)
This will allow you to perform sorting without tricks:
SELECT *
FROM SomeTable
ORDER BY Actual_Date
Or run range queries that take advantage of the IX_SomeTable_ActualDate index:
SELECT *
FROM SomeTable
Where Actual_Date Between DATEADD(d,-7,GETDATE()) AND GETDATE()
If you have 1000 rows, you could get 1000 times better performance.
Existing applications won't even notice the change. Newer queries and applications will be able to take advantage of indexing and sorting
I had a similar problem: my column (<my_date_field>) had date values in the form of
2021-01
2021-02
2021-10
2021-12
and so on, with data type of nvarchar(4000), and I always ran into the Conversion failed when converting date and/or time from character string. error (when trying e.g. CAST(<my_date_field> AS DATE) or CAST(CAST(<my_date_field> AS VARCHAR(7)) AS DATE) etc.)
I was able to convert them to date with the following code:
SELECT
CONVERT(date, <my_date_field> + '-01') AS first_day_of_month
FROM my_table
which resulted in
2021-08-01
2021-07-01
2021-06-01
2021-05-01

Nvarchar to Date

In my table I have
ReportingWeek (Date) eg 2017-03-19
BookedWeek (nvarchar(12) eg 07.2017
I would like to select on rows where the BookedWeek is in the last 17 weeks.
Do I need to convert BookedWeek to a date, then query it for last 17 weeks, or can it be done directly as a nvarchar?
Yes, you have to convert string to datetime first, see this example :
SELECT * WHERE DATEDIFF(DAY,cast('2017-03-19' AS datetime),GETDATE())<17
You don't need to convert the value to a date. If you want to treat it as a date, that is reasonable. This is especially important if you want to compare it to "real world" dates.
I should note that if you are going to store the value as a string, you should store it in YYYYWW format (YYYY.WW is fine). That way, the values can be sorted and compared to each other.
No need to convert bookedweek to date. We can handle by string functions. Below query should give you the expected result, considering across the year too.
create table #tmp
(
bookedweek nvarchar(12)
)
insert into #tmp values ('07.2017'),('09-2017'),('01.2017'),('50.2016'),('52.2016'),('13.2016'),('48.2016'),('49.2016')
select * from #tmp
where (year(getdate())=RIGHT(bookedweek,4) and datepart(week,getdate())- LEFT(bookedweek,2)<17)
OR (year(getdate()) - RIGHT(bookedweek,4)=1 and 53 - LEFT(bookedweek,2) + datepart(week,getdate()) < 17)
drop table #tmp
Here 53 is the total weeks in a calendar year.

How to perform arithmetic function in DATE TIME in SQL

I have four columns namely-
1. C_Date in YYYYMMDD format (varchar(255)) Eg. 20161231
2. C_Time in 4-digit Military format (varchar(255)) Eg. 2143
3. E_Date in YYYYMMDD format (varchar(255)) Eg. 20161230
4. E_Time in 4-digit Military format (varchar(255)) Eg. 1600
I want to Calculate the time between E event and C event. How can i perform this computation with a select statement?
Pretty simple to create a date type from the component values:
with data as (select '20161231' as c_date, '2143' as c_time)
select
convert(
datetime,
stuff(stuff(stuff(c_date + ' ' + c_time, 12, 0, ':'), 7, 0, '-'), 5, 0, '-'),
120
) as c_datetime
from data;
Use datediff() to calculate the time difference. You didn't specify how you wanted the output to look so I won't attempt a guess. There should be a hundred other questions out there with information relevant to your question though.
Also note that I did not append ':00' to the string to represent seconds. It seems to work though I couldn't track down an official document to confirm that. So to be safe you may want to tack that on as well. Arguably there could be a more universal format like ISO 8601 that would be a "better" solution. You get the idea though.
A small matter to convert your strings into a datetime. Then we use DateDiff() to calculate the differance between the two dates.
Declare #YourTable table (C_Date varchar(255),C_Time varchar(255),E_Date varchar(255),E_Time varchar(255))
Insert Into #YourTable values
('20161231','2143','20161230','1600')
;with cte as (
Select *
,CDT = try_convert(DateTime,C_Date+' '+stuff(C_Time,3,0,':'))
,EDT = try_convert(DateTime,E_Date+' '+stuff(E_Time,3,0,':'))
from #YourTable
)
Select CDT
,EDT
,Duration = concat(DateDiff(DD,EDT,CDT),' ',Format(DateAdd(Second,DateDiff(SECOND,EDT,CDT),'1899-12-31'),'HH:mm:ss'))
,AsSeconds = DateDiff(SECOND,EDT,CDT)
,AsMinutes = DateDiff(MINUTE,EDT,CDT)
From cte
Returns
CDT EDT Duration AsSeconds AsMinutes
2016-12-31 21:43:00 2016-12-30 16:00:00 1 05:43:00 106980 1783

SQL Server - add DATE part of DATETIME to TIME part of DATETIME

In SQL Server 2005 I am interrogating some old legacy data and I need to combine the date component of a datetime column with the time component from another column. Here's an example:
DateColumn: 2016-05-09 00:00:00.000
TimeColumn: 1899-12-30 12:26:00.000
I need the end result converted to the following DateTime:
ResultDateTime: 2016-05-09 12:26:00.000
I tried using:
CAST(DateColumn AS DATETIME) + CAST(TimeColumn AS TIME) AS ResultDateTime
But SQL Server 2005 doesn't recognize the type TIME.
Can someone please show me a way of doing that?
Many thanks!
convert the time column to string HH:MM:SS and add to the date column
ResultDatetIme = DateColumn + convert(varchar(10), TimeColumn, 108)
You can just use DATEADD and DATEDIFF, assuming that the time column's date portion is always 30/12/1899:
declare #t table (DateColumn datetime,TimeColumn datetime)
insert into #t(DateColumn,TimeColumn) values
('2016-05-09T00:00:00.000','1899-12-30T12:26:00.000')
select DATEADD(millisecond,DATEDIFF(millisecond,'18991230',TimeColumn),DateColumn)
from #t
Result:
-----------------------
2016-05-09 12:26:00.000
As you can see following data type supported in SQL 2005:
https://msdn.microsoft.com/en-us/library/ms187819(v=sql.90).aspx
Use datetime and smalldatetime, The smalldatetime data type stores dates and times of day with less precision than datetime. The Database Engine stores smalldatetime values as two 2-byte integers. The first 2 bytes store the number of days after January 1, 1900. The other 2 bytes store the number of minutes since midnight.
datetime values are rounded to increments of .000, .003, or .007 seconds, as shown in the following table.
SELECT CAST('2016-05-09 00:00:00.000' AS DATETIME) + CAST('1900-01-01 12:26:00.000' AS smalldatetime) AS ResultDateTime
Result: 2016-05-09 12:26:00.000
So you can use datetime and smalldatetime, hope fully that will work for you.
Let me know if any issue. love to resolve :)