如何在SQL Server中保存波斯日期时间?

8

在过去的项目中,我尝试在应用程序的逻辑层中将时间格式保存为公历日期,并将公历日期转换为波斯语,但我已经厌倦了这种方式。

我需要在SQL服务器中以波斯语格式保存和还原日期时间,而不进行任何转换。

SQL服务器中datetime2类型能否存储波斯日期时间?

如果不能,什么是存储波斯日期时间的最佳方法?


2
这个链接有用吗: https://www.codeproject.com/Articles/28129/Creating-a-CLR-Persian-Date-Convertor-Function-for - PaulF
1
“时间格式”是什么意思?日期没有格式,它们是二进制值。您可以在客户端基于波斯日历创建DateTime对象,将其保存到数据库中,并在再次检索时以波斯语显示。日历影响日期的计算方式,而不是它们的显示方式。 - Panagiotis Kanavos
1
例如,在我的计算机上,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
我认为那是一样的。谢谢。 - Ahmad Javadi Nezhad
1
选择格式(getdate(),'yyyy/MM/dd','fa-ir')。 - AliNajafZadeh
3个回答

13

datetime2在SQL Server中使用公历。

如果你想使用基于波斯历的日期,那么你需要创建一些函数在SQL代码中调用以进行转换,或者你需要创建一个用户定义类型来存储数据。

这里是一些可以在波斯历和公历之间进行转换的函数示例。我没有尝试过它们,所以我不知道它们是否有效或质量如何。

我找不到一个关于创建波斯日期的UDT的示例,但这是有关UDT的文档

个人而言,我会将日期存储在 SQL Server 中作为 UTC 格里高利日期时间 datetime2。我会在应用程序数据层中编写转换代码,在保存到和从 SQL Server 加载时进行转换,或者在显示给用户/从用户检索 DateTime 时进行转换。

UTC 是世界上的日期和时间标准,特别是对于科学和工程领域,因此 SQL Server 和 .Net 已经使用它构建。使用 UTC 也是有意义的,这样您可以从现有的 SQL Server 和 .Net 代码中获得最大的好处。当然,您的用户仍然希望能够使用波斯历来编写和读取 DateTime,因此在向用户显示之前或用户提供后进行转换是有意义的。


1
一个计算列是否有意义,它可以应用转换函数将公历日期转换为波斯日期?我认为计算列是即时计算的,而不是保存在数据库中的。存储转换数据的计算列可以是varchar类型。 - RBT
3
为什么要使用计算列?是否有问题需要解决?日期没有格式,它们是二进制值。如果您想以特定格式显示日期,只需在应用程序中使用适当的语言环境或设置格式字符串即可。只有在日期计算不同时才需要更改存储类型。 - Panagiotis Kanavos

3
您可以使用以下函数将日历转换为波斯语,反之亦然。
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

1
我认为用户自定义类型是更好的想法,但无论如何感谢您的回答。 - Ahmad Javadi Nezhad
1
谢谢,请添加“UDF_Persian_To_Julian”的示例。 - Mohsen Najafzadeh

3

您可以在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')

我希望你一切顺利


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接