How to save Hijri dates (0000/01/01-9999/01/01) in Microsoft SQL Server tables? What type of column?
I choose datetime2
, is it right?
CRE
This help me a lot.
Declare @Hdate nvarchar(50)
set @Hdate = convert(varchar(10),convert(date,convert(varchar(12),getdate(),131),103),112)
You can use column of type (Hijri_Date varchar(10)) and it will be easy to save and easy to make reports and query between 2 dates. In C# asp.net use the following steps:
1- Add script manager to your web-form. and set the property EnableScriptGlobalization = true , EnableScriptLocalization = true
2- Add HijriDate text box.
3- Add Button to select Hijri Date.
4- Add CalendarExtender from Ajaxtoolbox and add the following properties for example PopupButtonID="btnDate" TargetControlID="txtapptdate".
5- Change the format property for CalendarExtender to dd/MM/yyyy.
6- change the property for text-box read only = true.
7- Add the following culture values to your header page in html to convert calender from Gregorian date to Hijri date : UICulture="ar" Culture="ar-SA".
8- When you save and insert to SQL server the date you can use the value as usual Hijri_Date.Text
9- to compare later and make filter and search screen or reports and if you need to find out the records between 2 dates use the format function to change the DATE output format and convert function to convert varchar to date in select statement like this:
select format(cast(Hijri_date as date),'dd/MM/yyyy','ar-sa')
from Table1
where Hijri_date between '10/05/1439' and '20/10/1439'
I dont know why people downvote this but if you have ever written a program that interacts with Persian dates and you need to generate reports based on dates and times you will understand why you should store it as pure string value. sql server lacks the ability to convert UTC to different time zones and you should use clr to do that and many hosting environment does not allow you to do that
I recommend you to store them in fixed format like yyyy/MM/dd HH:mm:ss
in char(19)
column if you ever want to have reports based on Hijri date, also store the UTC time in another column for further uses or globalization.
If you store them with the pattern I mentioned above you can compare them easily and also get specific part of the date time (year, hour, ...) just by extracting part of the value by using SUBSTRING
Keep in mind that you can always store the UTC time with time zone in your database but my experience shows that you will have difficulties with reports soon or later.
Another point is that never try to store Hijri dates in DateTimes because you can not do that. for example 1394/02/31
is a Hijri date but you can not have 31st day of February in DateTime.
Assume you want to generate report of items that are created in each day. if you store the date just as UTC you must to convert each date time to Hijri by specific time zone difference and daylight time saving and then group by it and you will face huge performance degradation. For example try to calculate the report for 1393/12/20
to 1394/01/10
and then you will understand why not use UTC date times for this kind of reporting stuffs.
Store them in datetime2 -- they should go in as utc dates. If you have strings, convert them using CONVERT passing the style code 131.
DECLARE @HijriDateString VARCHAR(10) = '02/02/1435';
declare @HijriDate datetime2 = CONVERT(DATETIME, @HijriDateString, 131);
declare @FormattedOuput varchar(255) = convert(nvarchar(255), @HijriDate, 131);
select @HijriDateString as [original string], @HijriDate as [parsed datetime2], @FormattedOuput as [formatted output]
-- original string parsed datetime2 formatted output
-- 02/02/1435 2013-12-05 00:00:00.0000000 2/02/1435 12:00:00.0000000AM
Then when you present the date to the user, you format it back out as Hijri.
By keeping it in datetime2, you can do proper date arithmetic, using things like
MyDateColumn < getutcdate()
To do correct comparisons.
EDIT for @Dotctor's question Does a normal grouping by day not work? There's every chance I'm missing something key, so I'd be glad to learn
begin tran
create table #hijriDateExample (id int, d datetime2)
insert into #hijriDateExample values
(1, CONVERT(DATETIME, '02/02/1435 01:00' , 131)),
(2, CONVERT(DATETIME, '02/02/1435 22:00' , 131)),
(3, CONVERT(DATETIME, '03/02/1435 04:00' , 131))
select dateadd(DAY,0, datediff(day,0, d)), count(*) as [numberOfDays] from #hijriDateExample
group by dateadd(DAY,0, datediff(day,0, d))
-- 2013-12-05 00:00:00.000 2
-- 2013-12-06 00:00:00.000 1
rollback tran