Try/Catch in UDF not possible? How to "TryCast" a varchar to datetime? - sql

how can i convert a varchar parameter into datetime and if cast fails use GetDate() as default?
I've tried to put it in a Try/Catch but apparently that doesn't work in a UDF. It also does not work to simply check if the datetime is null, because it'll throw an exception('The conversion of a char data type to a datetime data type resulted in an out-of-range datetime value'):
CREATE FUNCTION [dbo].[getRZUInfo]
(
#IMEI varchar(20),
#StrDeliveryDate varchar(20)
)
RETURNS VARCHAR(8000)
AS
BEGIN
DECLARE #Info VARCHAR(8000)
DECLARE #DeliveryDate datetime;
SET #DeliveryDate = Convert(datetime,#StrDeliveryDate,102);
IF #DeliveryDate IS NULL
SET #DeliveryDate=GetDate();
SELECT #Info = COALESCE(#Info + '|', '') + 'TAT_B2B: ' + Convert(varchar,tabData.TAT_B2B) + ', AC' + Convert(varchar,tabData.fimaxActionCode) + ', Diff: ' + Convert(varchar,DateDiff(day,tabData.Received_date,#DeliveryDate))
FROM tabData
WHERE (SSN_Number = #IMEI) AND (Received_Date >= DATEADD(month, -3, #DeliveryDate))
ORDER BY SSN_Number,Received_Date DESC
return #Info
END

SET #DeliveryDate = CASE
WHEN Isdate(#StrDeliveryDate) = 1 THEN
CONVERT(DATETIME, #StrDeliveryDate, 102)
ELSE Getdate()
END

A common flaw with IsDate is that it is unable to take in a date format specifier that CAST/CONVERT can.
See this:
set dateformat dmy
declare #StrDeliveryDate varchar(20) set #StrDeliveryDate = '2011.12.13'
select CASE
WHEN Isdate(#StrDeliveryDate) = 1 THEN
CONVERT(DATETIME, #StrDeliveryDate, 102)
ELSE Getdate()
END
output: 2011-03-21 22:19:54.683
This is a better function for testing 102-formatted dates specifically. Actually 102 is much easier, this is flexible enough to pick up yy/yyyy, m/mm, d/dd.
create function dbo.Is102Date(#any varchar(50))
-- 102 = yyyy.mm.dd
returns bit as begin
set #any = ltrim(rtrim(#any))
declare #theyear varchar(10)
set #TheYear = case
when #any like '%[^0-9.]%' then null
when #any like '[0-9][0-9].%[0-9].%[0-9]' then
case when LEFT(#any,2) >=50
then '19'+LEFT(#any,2)
else '20'+LEFT(#any,2)
end
when #any like '[0-9][0-9][0-9][0-9].%[0-9].%[0-9]' then
LEFT(#any,4)
end
declare #YYYYMMDDToTest varchar(50)
set #YYYYMMDDToTest = case
when #TheYear is not null then
#TheYear
+ -- month
SUBSTRING(#any, charindex('.',#any) +1,
charindex('.',#any,charindex('.',#any)+1)-
charindex('.',#any)-1)
+ -- day
right(#any,charindex('.',reverse(#any))-1)
end
return ISDate(#YYYYMMDDToTest)
end
GO
Use it instead of ISDATE to test for 102-formatted dates in varchar.

Just checking when Null
IF #StrDeliveryDate IS NULL
SET #DeliveryDate = GetDate();
ELSE
SET #DeliveryDate = Convert(datetime, #StrDeliveryDate, 102);

Related

How to convert '01/01/0001' to datetime2

I was trying to display a '01/01/0001' from sql if the value is null. But when I convert the value into datetime2, it says:
Msg 517, Level 16, State 3, Line 18
Adding a value to a 'datetime2' column caused an overflow.
this is what I tried:
Declare #NewDate as DateTime2
SELECT #Tem = Ab.Date_out
FROM Timesheet_header Ab
WHERE (Ab.Employee_id = 3424)
AND (Ab.Work_date BETWEEN ('2017-08-31') AND ('2017-08-31'))
print #Tem
if(#Tem IS NULL)
Begin
set #NewDate = CONVERT(VARCHAR, DATEADD(DAY,-5,CAST('0001-01-01' AS DATETIME2)),100)
--some select clause here
End
else
Begin
--some select clause here
End
print #Tem
print #NewDate
Here is your problem:
DATEADD(DAY,-5,CAST('0001-01-01' AS DATETIME2))
Datetime2 min value is 0001-01-01, but you try to create a value that's 5 days before.
From MSDN:
Date range 0001-01-01 through 9999-12-31
Also, your #NewDate variable is of type datetime2, but you try to populate it with varchar(100) -
set #NewDate = CONVERT(VARCHAR, DATEADD(DAY,-5,CAST('0001-01-01' AS DATETIME2)),100)
That makes no sense. If anything, you should be doing something simple like this:
SET #NewDate = '0001-01-01';

Handle Julian and Real Times in one query

Hi Below is some sample data
DECLARE #Time TABLE (
[Time] VARCHAR(250),
[Count] VARCHAR(250)
)
INSERT INTO #Time ([Time],[Count])
VALUES
('13:52','2'),
('13:53','2'),
('13:54','5'),
('13:55','3'),
('13:56','3'),
('13:57','1'),
('13:58','4'),
('13:59','1'),
('130','72'),
('1300','61'),
('1301','40'),
('1302','51'),
('1303','53'),
('1304','59'),
('1305','62'),
('1306','36'),
('1307','56'),
('1308','52')
Select * from #Time
Is there a way to handle both data types so that it outputs as a real time
I use a function that partly works but am getting and error each time:
Msg 8116, Level 16, State 1, Line 1
Argument data type varchar is invalid for argument 2 of dateadd function.
The function I use is as follows and wondered if this can be adopted/changed to account for the poor data eg both types of Times (Julian/Regular).
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
-- Add the parameters for the function here
#JulianTime INT
)
RETURNS DATETIME
AS
BEGIN
-- Declare the return variable here
DECLARE #Result DATETIME
-- Add the T-SQL statements to compute the return value here
IF #JulianTime >= 0 AND #JulianTime < 1440 -- this ensures that the result will be in the range of a datetime data type
SET #Result = DATEADD(MINUTE, #JulianTime, CAST('00:00' AS TIME))
ELSE
SET #Result = CAST('00:00' AS TIME)
-- Return the result of the function
RETURN #Result
END
GO
ADDITION:
The COMPLETE datetime function is here:
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianDateTimeToSQLDateTime] (
-- Add the parameters for the function here
#JulianDate INT,
#JulianTime INT = 0
)
RETURNS DATETIME
AS
BEGIN
-- Declare the return variable here
DECLARE #Result DATETIME
-- Add the T-SQL statements to compute the return value here
IF #JulianDate > 640333 -- this ensures that the result will be in the range of a datetime data type
BEGIN
SET #Result = DATEADD(DAY, (#JulianDate-429), CAST('Jan 1 0001' AS DATETIME2))
IF #JulianTime < 1440 AND #JulianTime >= 0 -- this ensures that the time is between 00:00 and 23:59
SET #Result = DATEADD(MINUTE, #JulianTime, #Result)
END
ELSE
SET #Result = 'Jan 1 1753'
-- Return the result of the function
RETURN #Result
END
GO
I am not sure what exactly are you trying to do from your give information. But I tried to modify the function to return time when I pass it JulianTime as a varchar. Here is the code -- (try to make changes accordingly though)
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
-- Add the parameters for the function here
#JulianTime VARCHAR(255)
)
RETURNS TIME(0)
AS
BEGIN
-- Declare the return variable here
DECLARE #Result TIME(0), #HOUR VARCHAR(2), #MINUTES VARCHAR(2)
-- DECLARE #JulianTime VARCHAR(255)
-- SET #JulianTime = '13:02'
SET #HOUR = SUBSTRING(#JulianTime, 1, 2)
IF(LEN(#JulianTime) = 4)
SET #MINUTES = SUBSTRING(#JulianTime, 3, 2)
IF(LEN(#JulianTime) = 5)
SET #MINUTES = SUBSTRING(#JulianTime, 4, 2)
SET #Result = CONCAT(#HOUR, ':', #MINUTES)
-- PRINT #RESULT
-- Return the result of the function
RETURN #Result
END
GO
I've updated the FUNCTION.
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
#timeString varchar(250)
)
RETURNS TIME
AS
BEGIN
DECLARE #Result TIME ;
/* Ensure that we're working with a fixed date */
DECLARE #epoch datetime = '19000101' ;
/* Check the string for ':' */
IF CHARINDEX(':',#timeString) > 0
/* Can #timeString be parsed as a valid time? */
SET #Result = TRY_PARSE(#timeString AS time) ; /* Returns NULL if bad time string. */
ELSE
/* No ':' so check if valid julian time. */
IF TRY_CONVERT(int,#timeString) IS NOT NULL AND CONVERT(int,#timeString) BETWEEN 0 AND 1439
SET #Result = CAST( DATEADD(minute, CONVERT(int,#timeString), #epoch) AS time) ;
ELSE
SET #Result = NULL ;
RETURN #Result ;
END
http://dbfiddle.uk/?rdbms=sqlserver_2016&fiddle=1ca82cd76b2932593262601b1742f602
This will only work if you're using something greater than SQL 2012+ because of TRY_PARSE and TRY_CONVERT. If you're lower than 2012, you can modify that bit to do what those functions essentially do.
Select
CASE WHEN CHARINDEX(':',[Time]) > 0 THEN CAST([Time] AS TIME) ELSE DATEADD(MINUTE, TRY_CAST([Time] AS INT), CAST('00:00' AS TIME)) END AS [RealTime],
*
from #Time
This appears to do the trick, thanks for the valuable input
For SQL 2008, use this function:
CREATE FUNCTION [dbo].[udf_TR_PROTOS_JulianTimeToSQLDateTime]
(
#timeString varchar(250)
)
RETURNS TIME
AS
BEGIN
DECLARE #Result time ;
/* Ensure that we're working with a fixed date */
DECLARE #epoch datetime = '19000101' ;
/* Check the string for ':' */
IF CHARINDEX(':',#timeString) > 0
IF ISDATE(#timeString) = 1
/* Is #timeString a valid time object? */
SET #Result = CAST(#timeString AS time) ;
ELSE
SET #Result = NULL ;
ELSE
/* No ':' so check if valid julian time. */
IF ISNUMERIC(#timeString) = 1 AND CONVERT(int,#timeString) BETWEEN 0 AND 1439
SET #Result = CAST( DATEADD(minute, CONVERT(int,#timeString), #epoch) AS time) ;
ELSE
SET #Result = NULL ;
RETURN #Result ;
END

Getting FRACTIONAL difference (YEARS) between two dates in T SQL

I need to detect a difference between two dates, such that when Date_1 = 12-jan-2010 and Date_2 = 01-jan-2016 I would NOT get 6 but a number < 6.
SELECT DATEDIFF(YEAR,'12-jan-2010','01-jan-2016')
DATEDIFF returns 6 in the above case.
It depends on required precision, try following:
SELECT DATEDIFF(DAY, #d1, #d2)/365.25
I guess this resolves,
DECLARE #STARTDATE DATE='12-jan-2010'
DECLARE #ENDDATE DATE='01-jan-2016'
DECLARE #TOTALDAY DECIMAL(18,2)=DATEDIFF(day,#STARTDATE,#ENDDATE)
DECLARE #AVGYEAR DECIMAL(18,2)= ((365*DATEDIFF(YEAR,#STARTDATE,#ENDDATE))+
dbo.LEAP_YEAR(#STARTDATE,#ENDDATE))/CONVERT(DECIMAL(18,2),
DATEDIFF(YEAR,#STARTDATE,#ENDDATE))
SELECT CONVERT(decimal(18,2),#TOTALDAY/#AVGYEAR) AS DiffDate ---This will provide you result in decimal
this the function which return no of leap years between dates.
ALTER FUNCTION LEAP_YEAR(#START DATE,#END DATE)
RETURNS INT
AS BEGIN
DECLARE #COUNT INT = 0,#Z INT = DATEPART(YYYY,#START)
DECLARE #X INT =DATEPART(YYYY,#START)
DECLARE #Y INT =DATEPART(YYYY,#END)
IF (DATEPART(MM,#START) >2)
SET #X=#X+1
IF (DATEPART(MM,#END) <2)
SET #Y=#Y-1
WHILE (#X <= #Y)
BEGIN
SET #COUNT = #COUNT +
(CASE WHEN (#X%4 = 0 AND #X%100 !=0) OR #X%400 = 0
THEN 1
ELSE 0 END)
SET #X = #X + 1
END
RETURN #COUNT
END
If I've got it right. Just Add result of DATEDIFF (6 in this case) to the start date if it > the end date then just subtract 1 year so you will get 5 full years:
DECLARE #StartD DATETIME;
DECLARE #FinalD DATETIME;
SET #StartD = '12-jan-2010';
SET #FinalD = '11-jan-2016';
SELECT DATEDIFF(YEAR,#StartD,#FinalD)
- CASE WHEN DATEADD(YEAR,DATEDIFF(YEAR,#StartD,#FinalD),#StartD)>#FinalD
THEN 1 ELSE 0 END
First of all, I wish to thank all those that spent time trying to provide a simple and reliable solution. Finally, I decided to resolve it as follows:
Supposed that I want to know if #n full years passed between two dates, then:
DECLARE #n INT ;
DECLARE #Old_Date DATETIME ;
DECLARE #New_Date DATETIME ;
SET #n = <some_value> ;
SET #Old_Date = <some_value> ;
SET #New_Date = <some_value> ;
IF (DATEADD(YEAR ,#n , #Old_Date) <= #New_Date)
SET #Result = 'YES' ;
ELSE
SET #Result = 'NO' ;
[of course, a check needs to be included to verify that #Old_Date < #New_Date]
I can't say this can be proved (mathematically) as correct in all possible scenarios, but it provides the needed answer to me.
Thanks to all again.

convert date to spanish in sql

I am running a report with multiple fields in english. I have 2 date fields at the end of the report, one has to be in English and the other in Spanish. The format the date needs to be in is ie November 1, 2012. I need the spanish to be Novembre 1, 2012. I cannot get the last field of the report to produce in spanish. I am running in sql server 2005.
Maybe is cumbersome, but I don't see how to do it on an easier way.
First, create a function. This function will make use of system view sys.syslanguages to get the correct name of month in spanish. Parameters are a valid date and language (alias on sys.syslanguage view).
CREATE FUNCTION [dbo].[fn_GetMonthName] (
#Date DATETIME,
#Language NVARCHAR(100)
)
RETURNS NVARCHAR(400)
AS
BEGIN
DECLARE #i INT, #m INT,#mlist NVARCHAR(1000)
SET #m = MONTH(#Date)
SET #mlist = (SELECT months FROM sys.syslanguages WHERE ALIAS = #language)
SET #i = 1
WHILE(#i < #m)
BEGIN
SET #mlist = REPLACE(#mlist, SUBSTRING(#mlist,1,CHARINDEX(',',#mlist)) ,'')
SET #i = #i + 1
END
SET #mlist = (CASE CHARINDEX(',',#mlist) WHEN 0 THEN #mlist ELSE SUBSTRING(#mlist,0,CHARINDEX(',',#mlist) ) END )
RETURN #mlist
END
GO
Then call the function anywhere you need to:
SELECT CONVERT(VARCHAR(20), GETDATE(), 100) AS CurrentDate,
dbo.fn_GetMonthName (GETDATE(), 'Spanish') AS [Mes-Month]
Result:
CurrentDate Mes-Month
May 24 2013 12:02AM Mayo
Taken from Get Language specific Month Name from SQL
Take a look at: http://www.sqlservercurry.com/2010/11/change-default-language-for-sql-server.html
You can temporarily set the language to spanish, not sure how feasible this is for you. The other way to do it would be to write your own months function, and maybe pass it a 2nd parameter that then decides what the output would be.
This function will translate the month within a string it's based on the sys.syslanguages table.
i.e. SELECT dbo.fn_tranMonth(2,0,'1 déc. 2014 10:26:14 UTC+00:00')
Results:
1 Dec. 2014 10:26:14 UTC+00:00
CREATE FUNCTION [dbo].[Split] (#sep char(1), #s varchar(8000))
RETURNS table
AS
RETURN (
WITH Pieces(pn, start, stop) AS (
SELECT 1, 1, CHARINDEX(#sep, #s)
UNION ALL
SELECT pn + 1, stop + 1, CHARINDEX(#sep, #s, stop + 1)
FROM Pieces
WHERE stop > 0
)
SELECT
SUBSTRING(#s, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS s
FROM Pieces
)
GO
CREATE FUNCTION dbo.fn_tranMonth
(
#fromLan INT
,#toLan INT
,#string VARCHAR(MAX)
)
RETURNS
VARCHAR(50)
AS
BEGIN
DECLARE #TTTT AS TABLE(PK INT IDENTITY(1,1)
,fromMonth VARCHAR(50)
,toMonth VARCHAR(50)
)
DECLARE
#fromMonths VARCHAR(200)
,#toMonths VARCHAR(200)
,#fromMonth VARCHAR(20)
,#toMonth VARCHAR(20)
,#rowNum INT=12;
SELECT #fromMonths=shortmonths
FROM SYS.syslanguages
WHERE langid=#fromLan;
SELECT #toMonths=shortmonths
FROM sys.syslanguages
WHERE langid=#toLan;
INSERT #TTTT(fromMonth)
SELECT S
FROM dbo.Split(',',#fromMonths);
DECLARE #TTTT2 AS TABLE(PK INT IDENTITY(1,1)
,toMonth VARCHAR(50)
)
INSERT #TTTT2(toMonth)
SELECT S
FROM dbo.Split(',',#toMonths);
UPDATE #TTTT
SET toMonth=B.toMonth
FROM
#TTTT A
JOIN #TTTT2 B ON A.PK=B.PK;
DECLARE
#loopPos INT=0
,#returnMonth VARCHAR(50);
WHILE #loopPos<#rowNum
BEGIN
SET #loopPos+=1;
SELECT
#fromMonth=fromMonth
,#toMonth=toMonth
FROM #TTTT
WHERE PK=#loopPos;
SET #string=REPLACE(#string,#fromMonth,#toMonth);
END;
RETURN #string;
END
try this:
SELECT CONVERT(VARCHAR(10),GETDATE(), 103)
or
this code, return a VARCHAR(10) with date EN ESPAÑOL, leches.
IDEA (separator used: '-'):
Get format YYYY-MM-DD NVARCHAR(10).
Get format DD-MM-YYYY nvarchar(10)
Use the function
sample:
select dbo.date2txt(GETDATE ())
function to create:
create function [dbo].[AFecha] (
#fecha NVARCHAR(10)
)
returns NVARCHAR(10)
as
begin
Declare #r nvarchar(10)
if substring(#Fecha,3,1) = '-'
set #r = #Fecha
else
set #r = substring(#fecha,9,2)+'-'+substring(#fecha,6,2)+'-'+left(#fecha,4)
Return #r
End
go
create FUNCTION [dbo].[NTSDate](#fecha DateTime)
RETURNS nVarChar(10) AS
BEGIN
DECLARE #salida nVarChar(10)
set #salida = STR(year(#fecha),4,0) + '-' + RIGHT('0' + LTRIM(month(#fecha)),2) + '-' + RIGHT('0' + LTRIM(day(#fecha)),2)
return (#salida)
End
go
ALTER function [dbo].[Date2Txt](#Fecha as datetime) returns nvarchar(10)
as
begin
return dbo.afecha(dbo.NTSDate(#Fecha))
end
go
You can do the following:
FORMAT(GETDATE(), 'MMMM d,yyyy','es-US')
The last parameter for format datetime is an optional culture parameter that does exactly what you need when passed the right culture.
If you needed to localize to a different language you could find the string to do so from the link below.
https://learn.microsoft.com/en-us/windows-hardware/manufacture/desktop/default-input-locales-for-windows-language-packs?view=windows-11

How to extract date fields from string/text field in sql server 2005

There is a text filed in a table called as description. I would like to extract two date fields from this string when there is an occurrence of '~' character using sql server 2005 stored procedure. Help me out in this case.
Example: string: '长期租金;10/1/2012 ~ 10/31/2012'. At occurrence of ~ operator I would like to have from-date: 20121001 and to-date:20121031.
Here is a method which will give the start and end dates. I left most of the testing selects in place but commented out.
DECLARE #string AS NVARCHAR(255)
DECLARE #Seperator as char(1) = '~'
declare #CharStartDate as varchar(10)
declare #CharStopDate as varchar(10)
declare #StartDate as date
declare #StopDate as date
declare #I int
--SET #string = 'xvvvvvvcc;1/09/2012 ~ 1/10/2012xx'
--SET #string = 'xvvvvvvcc;12/31/2012 ~ 1/1/2012xx'
--SET #string = 'xvvvvvvcc;12/1/2012 ~ 10/0/2012xx'
SET #string = 'xvvvvvvcc;1/2/2012 ~ 1/3/2012xx'
--longest date 12/31/2011 = 10
--shortest date 1/1/2012 = 8
-- width of seperator = 3
SELECT
#CharStartDate = substring (#string, CHARINDEX(#Seperator,#string)-11,10)
,#CharStopDate = substring (#string, CHARINDEX(#Seperator,#string)+2,10)
--SELECT #CharStartDate,#CharStopDate
select #I = ascii(substring(#CharStartDate,1,1))
While #I > 57
BEGIN
set #CharStartDate = substring(#CharStartDate,2,10)
--select #CharStartDate
select #I = ascii(substring(#CharStartDate,1,1))
END
select #I = ascii(substring(REVERSE(#CharStopDate),1,1))
While #I > 57
BEGIN
set #CharStopDate = REVERSE(substring(REVERSE(#CharStopDate),2,10))
--select #CharStopDate
select #I = ascii(substring(REVERSE(#CharStopDate),1,1))
END
--select ascii(';'),ascii('9'),ascii('8'),ascii('7'),ascii('6'),ascii('6'),ascii('4'),ascii('3'),ascii('2'),ascii('1'),ascii('0')
SELECT #StartDate = #CharStartDate,#StopDate = #CharStopDate
--SELECT #I,#string,#Seperator,#CharStartDate,#CharStopDate,#StartDate,#StopDate
select datediff(dd,#StartDate,#StopDate) AS 'DateDiff',#StartDate as 'Start Date',#StopDate as 'Stop Date'
I will leave it to you to check for the seperator.
CREATE FUNCTION [dbo].[RemoveAlphaCharacters](#Temp nvarchar(max))
RETURNS nvarchar(max)
AS
BEGIN
WHILE PatIndex ('%[^0-9~/]%', #Temp) > 0
SET #Temp = Stuff(#Temp, PatIndex('%[^0-9~/]%', #Temp), 1, '')
RETURN #Temp
END
DECLARE #string nvarchar(max) = '长期租金;10/1/2012 ~ 10/31/2012'
SELECT CONVERT(date, SUBSTRING([dbo].[RemoveAlphaCharacters](#string), 0,
CHARINDEX('~', [dbo].[RemoveAlphaCharacters](#string))), 101) AS BDate,
CONVERT(date, SUBSTRING([dbo].[RemoveAlphaCharacters](#string),
CHARINDEX('~', [dbo].[RemoveAlphaCharacters](#string)) + 1,
CHARINDEX('~', REVERSE([dbo].[RemoveAlphaCharacters](#string)))), 101) AS EDate
In this instance you can use the following but really you need an exists clause or something like that to test the string for the tilde (~) and as everyone else has stated, this only works if the string always has a semicolon(;) and a tilde(~). You can convert to the strings into datetime fields if you need.
I have placed the string in a variable to make it easier to read...
DECLARE #string AS NVARCHAR(255)
SET #string = '长期租金;10/1/2012 ~ 10/31/2012'
SELECT StartDate = SUBSTRING(#string,CHARINDEX(';',#string)+1,LEN(#string)-CHARINDEX('~',#string)-1)
,EndDate = LTRIM(RIGHT(#string,LEN(#string)-CHARINDEX('~',#string)))
i have never used the older version of SQL cause i just graduated but doesnt it have the EXTRACT() function?.. The syntax goes like this below.
SELECT First_Name ,
EXTRACT ( CAST(Created_date AS DATE) FROM Created_date ) AS Date_only ;
You specify 'First_name' to let SQL know you want it as a column and 'created_date' is the field from which youre trying to separate the date. the cast function converts your field to DATE value before extractig it.
i hope this helps . thank you. if im wrong please let me know i would like to improve myself.