اشکال در تبدیل تاریخ شمسی به میلادی
باسلام در sql تاریخ شمسی توسط فایل PersianToGregorian تبدیل به تاریخ میلادی می کنم مورخه 1404/02/31 را یک روز جلوتر نشان میده لطفا راهنمایی فرمایید ایراد کار کجاست
کد sql
ALTER FUNCTION [dbo].[PersianToGregorian](@DateStr varchar(10))RETURNS DATE
AS
BEGIN
declare @YYear int
declare @MMonth int
declare @DDay int
declare @epbase int
declare @epyear int
declare @mdays int
declare @persian_jdn int
declare @i int
declare @j int
declare @l int
declare @n int
declare @TMPRESULT varchar(10)
declare @IsValideDate int
declare @TempStr varchar(20)
DECLARE @TmpDateStr varchar(10)
SET @i=charindex('/',@DateStr)
IF LEN(@DateStr) - CHARINDEX('/', @DateStr,CHARINDEX('/', @DateStr,1)+1) = 4
BEGIN
-- SET @TmpDateStr = dbo.ReversDate(@DateStr)
IF ( ISDATE(@TmpDateStr) =1 )
RETURN @TmpDateStr
ELSE
RETURN NULL
END
ELSE
SET @TmpDateStr = @DateStr
IF ((@i<>0) and
-- (dbo.SubStrCount('/', @TmpDateStr)=2) and
(ISNUMERIC(REPLACE(@TmpDateStr,'/',''))=1) and
(charindex('.',@TmpDateStr)=0)
)
BEGIN
SET @YYear=CAST(SUBSTRING(@TmpDateStr,1,@i-1) AS INT)
IF ( @YYear< 1300 )
SET @YYear =@YYear + 1300
IF @YYear > 9999
RETURN NULL
SET @TempStr= SUBSTRING(@TmpDateStr,@i+1,Len(@TmpDateStr))
SET @i=charindex('/',@TempStr)
SET @MMonth=CAST(SUBSTRING(@TempStr,1,@i-1) AS INT)
SET @MMonth=@MMonth-- -1
SET @TempStr= SUBSTRING(@TempStr,@i+1,Len(@TempStr))
SET @DDay=CAST(@TempStr AS INT)
SET @DDay=@DDay-- - 1
IF ( @YYear >= 0 )
SET @epbase = @YYear - 474
Else
SET @epbase = @YYear - 473
SET @epyear = 474 + (@epbase % 2820)
IF (@MMonth <= 7 )
SET @mdays = ((@MMonth) - 1) * 31
Else
SET @mdays = ((@MMonth) - 1) * 30 + 6
SET @persian_jdn =(@DDay) + @mdays + CAST((((@epyear * 682) - 110) / 2816) as int) + (@epyear - 1) * 365 + CAST((@epbase / 2820) as int ) * 1029983 + (1948321 - 1)
IF (@persian_jdn > 2299160)
BEGIN
SET @l = @persian_jdn + 68569
SET @n = CAST(((4 * @l) / 146097) as int)
SET @l = @l - CAST(((146097 * @n + 3) / 4) as int)
SET @i = CAST(((4000 * (@l + 1)) / 1461001) as int)
SET @l = @l - CAST( ((1461 * @i) / 4) as int) + 31
SET @j = CAST(((80 * @l) / 2447) as int)
SET @DDay = @l - CAST( ((2447 * @j) / 80) as int)
SET @l = CAST((@j / 11) as int)
SET @MMonth = @j + 2 - 12 * @l
SET @YYear = 100 * (@n - 49) + @i + @l
END
SET @TMPRESULT=Cast(@MMonth as varchar(2))+'/'+CAST(@DDay as Varchar(2))+'/'+CAST(@YYear as varchar(4))
RETURN Cast(@TMPRESULT as varchar(10))
END
RETURN NULL
END
1404/02/31==05/20/2025 در حالی که 05/21/2025 صحیح است
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
سلام امتحان کردم تمام سالها درسته فقط برای سال 1404 یک روز دیتر تبدیل میکنه یک روز اختلاف داره
PersianToGregorian
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
استاد گرامی و مدیریت بخش لطفا پاسخ دهید خیلی خیلی نیازه با تشکر
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
این کد (و مشابه اون) حتی در گذشته هم خیلی بد بوده!
تبدیل تاریخ میلادی به شمسی با دستور Format
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
متصفانه متوجه پاسخ شما نشدم این کد فقط برای 1404 ایراد داره یک روز عقب تر نشون میده
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
این کدی که شما گذاشتین مربوط به یک تابع MS SQL هست،
یعنی شما میخواین عملیات کار با تاریخ رو در سطح دیتابیس (database layer) انجام بدین.
گذشته از این که معمولا این دست عملیات در اپلیکیشن (business layer) پیاده میشه،
حتی اگر دلیل موجه و محکمی برای این کار دارین (پیاده سازی در لایه دیتابیس) باز هم نوشتن تابع اینچنینی کار اصولی نیست
و باید CLR function بسازین و از اون استفاده کنین (پست 11 تاپیکی که معرفی کردم اشاره به همین موضوع داره).
شما ممکنه با اضافه کردن چند IF و بررسی سال همین کد رو برای امسال هم استفاده کنین،
ولی ضمانتی نیست که در سالهای بعدی مشکلی نداشته باشه.
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
منم همین مشکل رو دارم امیدوارم به زودی حل بشه.
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
https://fakhravary.blogfa.com/post/351
CREATE Function dbo.[EnToPersian] (@date datetime)
Returns nvarchar(50)
as
BEGIN
RETURN FORMAT(CAST( @date AS DATE),'yyyy/MM/dd', 'fa-ir')
END
SELECT dbo.[EnToPersian](GETDATE())
CREATE FUNCTION dbo.[PersianToEn]
(
@Date NCHAR(10)
)
RETURNS NVARCHAR(10)
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;
DECLARE @iYear INT = CAST(SUBSTRING(@Date, 1, 4) AS INT);
DECLARE @iMonth INT = CAST(SUBSTRING(@Date, 6, 2) AS INT);
DECLARE @iDay INT = CAST(SUBSTRING(@Date, 9, 2) AS INT);
IF @iYear >= '1404'
SET @PERSIAN_EPOCH = 1948322;
ELSE
SET @PERSIAN_EPOCH = 1948321;
SET @Jofst = 2415020.5;
IF LEN(@Date) > 1
BEGIN
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;
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 CONVERT(NVARCHAR(11), CONVERT(DATETIME, (@jdn - @Jofst), 131), 120);
END;
SELECT dbo.[PersianToEn](dbo.[EnToPersian](GETDATE()))
نقل قول: اشکال در تبدیل تاریخ شمسی به میلادی
نقل قول:
نوشته شده توسط
fakhravari
https://fakhravary.blogfa.com/post/351
CREATE FUNCTION dbo.[PersianToEn]
...
...
IF @iYear >= '1404'
SET @PERSIAN_EPOCH = 1948322;
ELSE
SET @PERSIAN_EPOCH = 1948321;
SET @epyear = 474 + (@epbase % 2820);
...
...
سلام و روز خوش
در مورد تابع PersianToEn چند نکته دیده میشه:
1- با توجه به اون 2820 و 682 در فرمولها گویا بر اساس الگوریتم آقایان بهروز/بیرشک هست که بر پایه چرخه های 2820 ساله بنا شده،
این روش البته اشکال داره که همین عدم تشخیص کبیسه بودن سال 1403 یکیش هست.
2- چون نتیجه محاسبه (روزهای گذشته از رفرنس تاریخ) به داده datetime کانورت میشه،
پس یک محدودیت در کف تاریخ قابل تبدیل داریم که اول ژانویه 1900 هست
که همزمان میشه با 11 دی 1278 خورشیدی.
در کارهای تجاری و پرسنلی و تولیدی و ... که با تاریخ های معاصر سروکار داریم این هیچ مشکلی نداره
بخصوص که این الگوریتم از همین 1278 تا 1404 دقیق و درسته.
ولی اگر با وقایع تاریخی و سیاسی سروکار داشته باشیم باید فانکشن اصلاح بشه.
3- الان یک IF هست که کل تاریخ های بعد از 1403 رو در بر میگیره که این درست نیست،
چون این الگوریتم در همه تاریخهای بعد از 1403 نیست که اشکال داره :
احتمالا فقط اونهایی رو اشتباه محاسبه میکنه که سیکلشون رو گم میکنه (33 سال و ...)
پس اگه IF رو به 1404= درست کنین اونوقت باید تا سیکل گم شده بعدی رو درست محاسبه کنه (اگه همین 33 سال باشه میشه دست کم تا سال 1437)
وگرنه 1404 درست میشه ولی بعد از اون همه رو اشتباه برمیگردونه.
حالا این باید تست بشه برای قطعیت - ولی تا پایان 1436 هم اگه با همین ویرایش IF درست بشه برای کارهای عملی کفایت میکنه
و هیچ اپلیکیشنی در حال حاضر قرار نیست تا اون موقع بمونه.