在过去的项目中,我尝试在应用程序的逻辑层中将时间格式保存为公历日期,并将公历日期转换为波斯语,但我已经厌倦了这种方式。
我需要在SQL服务器中以波斯语格式保存和还原日期时间,而不进行任何转换。
SQL服务器中datetime2类型能否存储波斯日期时间?
如果不能,什么是存储波斯日期时间的最佳方法?
在过去的项目中,我尝试在应用程序的逻辑层中将时间格式保存为公历日期,并将公历日期转换为波斯语,但我已经厌倦了这种方式。
我需要在SQL服务器中以波斯语格式保存和还原日期时间,而不进行任何转换。
SQL服务器中datetime2类型能否存储波斯日期时间?
如果不能,什么是存储波斯日期时间的最佳方法?
datetime2
在SQL Server中使用公历。
如果你想使用基于波斯历的日期,那么你需要创建一些函数在SQL代码中调用以进行转换,或者你需要创建一个用户定义类型来存储数据。
这里是一些可以在波斯历和公历之间进行转换的函数示例。我没有尝试过它们,所以我不知道它们是否有效或质量如何。
我找不到一个关于创建波斯日期的UDT的示例,但这是有关UDT的文档。
个人而言,我会将日期存储在 SQL Server 中作为 UTC 格里高利日期时间 datetime2
。我会在应用程序数据层中编写转换代码,在保存到和从 SQL Server 加载时进行转换,或者在显示给用户/从用户检索 DateTime
时进行转换。
UTC 是世界上的日期和时间标准,特别是对于科学和工程领域,因此 SQL Server 和 .Net 已经使用它构建。使用 UTC 也是有意义的,这样您可以从现有的 SQL Server 和 .Net 代码中获得最大的好处。当然,您的用户仍然希望能够使用波斯历来编写和读取 DateTime
,因此在向用户显示之前或用户提供后进行转换是有意义的。
Create FUNCTION [dbo].[UDF_Persian_To_Julian](@iYear int,@iMonth int,@iDay int)
RETURNS bigint
AS
Begin
Declare @PERSIAN_EPOCH as int
Declare @epbase as bigint
Declare @epyear as bigint
Declare @mdays as bigint
Declare @Jofst as Numeric(18,2)
Declare @jdn bigint
Set @PERSIAN_EPOCH=1948321
Set @Jofst=2415020.5
If @iYear>=0
Begin
Set @epbase=@iyear-474
End
Else
Begin
Set @epbase = @iYear - 473
End
set @epyear=474 + (@epbase%2820)
If @iMonth<=7
Begin
Set @mdays=(Convert(bigint,(@iMonth) - 1) * 31)
End
Else
Begin
Set @mdays=(Convert(bigint,(@iMonth) - 1) * 30+6)
End
Set @jdn =Convert(int,@iday) + @mdays+ Cast(((@epyear * 682) - 110) / 2816 as int) + (@epyear - 1) * 365 + Cast(@epbase / 2820 as int) * 1029983 + (@PERSIAN_EPOCH - 1)
RETURN @jdn
End
第二个功能是:
Create Function dbo.[UDF_Gregorian_To_Persian] (@date datetime)
Returns NvarChar(10) AS
begin
Declare @gd As int
Declare @gm As int
Declare @gm2 As int
Declare @gy As int
Declare @gy2 As int
Declare @jy as int
Declare @jd as int
Declare @jm as int
Declare @days as int
Declare @g_d_m as int
Declare @Result As NVarChar(10)
set @gy = YEAR(@date)
set @gm = MONTH(@date)
set @gd = DAY(@date)
if @gy <= 1600
set @jy = 0
else
set @jy = 979
if @gy <= 1600
set @gy = @gy - 621
else
set @gy = @gy - 1600
if @gm > 2
set @gy2 = @gy + 1
else
set @gy2 = @gy
set @gm2 = @gm - 1
if @gm2 = 0
set @g_d_m = 0
else if @gm2 = 1
set @g_d_m = 31
else if @gm2 = 2
set @g_d_m = 59
else if @gm2 = 3
set @g_d_m = 90
else if @gm2 = 4
set @g_d_m = 120
else if @gm2 = 5
set @g_d_m = 151
else if @gm2 = 6
set @g_d_m = 181
else if @gm2 = 7
set @g_d_m = 212
else if @gm2 = 8
set @g_d_m = 243
else if @gm2 = 9
set @g_d_m = 273
else if @gm2 = 10
set @g_d_m = 304
else if @gm2 = 11
set @g_d_m = 334
set @days = (365 * @gy) + ((@gy2 + 3) / 4) - ((@gy2 + 99) / 100) + ((@gy2 + 399) / 400) - 80 + @gd + @g_d_m
set @jy = @jy + 33 * (@days / 12053);
set @days = @days % 12053
set @jy = @jy + 4 * (@days / 1461)
set @days = @days % 1461
set @jy = @jy + ((@days - 1) / 365);
if @days > 365
set @days = (@days - 1) % 365;
if @days < 186
set @jm = 1 + (@days / 31)
else
set @jm = 7 + ((@days - 186) / 30);
if @days < 186
set @jd = 1 + (@days % 31)
else
set @jd = 1 + ((@days - 186) % 30)
Return Convert(nvarchar(50),@jy) + '/' + RIGHT('0' + CAST(@jm AS VARCHAR(2)), 2) +'/' + RIGHT('0' + CAST(@jd AS VARCHAR(2)), 2)
end
SELECT [dbo].[UDF_Gregorian_To_Persian] ('2018-2-5') as PersianDate
结果如下:
1396/11/16
您可以在SQL SERVER 2016及以上版本中使用波斯语格式,例如以下函数:
ALTER FUNCTION [Fun].[PersianDateFormat]
(
@Date datetime , --تاریخ میلادی ورودی
@How tinyint =1 --0.numberFull and time 1.numbers 2.Month latter 3.Day latter 4.Month and Day latter 5.just Month 6.Just Day
)
RETURNS Nvarchar(30)
AS
BEGIN
DECLARE @PersianDate Nvarchar(30)
if @How = 0
SELECT @PersianDate=FORMAT(@Date, 'yyyy/MM/dd-hh:mm:ss', 'fa')
if @How = 1
SELECT @PersianDate=FORMAT(@Date, 'yyyy/MM/dd', 'fa')
if @How = 2
SELECT @PersianDate=FORMAT(@Date, 'yyyy/MMM/dd', 'fa')
if @how = 3
SELECT @PersianDate=FORMAT(@Date, 'yyyy/MM/ddd', 'fa')
if @how = 4
SELECT @PersianDate=FORMAT(@Date, 'yyyy/MMM/ddd', 'fa')
if @how = 5
SELECT @PersianDate=FORMAT(@Date, 'MMM', 'fa')
if @how = 6
SELECT @PersianDate=FORMAT(@Date, 'ddd', 'fa')
RETURN @PersianDate
END
您可以直接在查询中使用以下方法将日期转换为波斯语:
Select FORMAT(Getdate(), 'yyyy/MM/dd-hh:mm:ss', 'fa')
我希望你一切顺利
DateTime.Now.ToString(System.Globalization.CultureInfo.GetCultureInfo("fa-IR"))
返回14/01/1396 03:17:13 ب.ظ
,我不知道这是否正确。在所有应用程序中,对于所有文化,如果您想以某种方式显示日期,则设置应用程序的 CultureInfo 或在字段上使用格式字符串。默认文化来自用户的语言环境。如果用户使用fa-IR
,则DateTime.Now.ToString()
也应返回14/01/1396 03:17:13 ب.ظ
。 - Panagiotis Kanavos