aliila
یک شنبه 24 آذر 1392, 16:09 عصر
این دومین تابع تبدیل میلادی به شمسی که نوشتم کل تاریخ مابین ۴۷۴/01/01 تا 3293/12/29 به عبارت دیگر برای دوره ۲۸۲۰ سال اخیر از سال ۴۷۴ تا ۳۲۹۳ هجری خورشیدی رو شامل میشه
سعی کردم از سال ۴۷۴ به بعد باشه تا الگوریتم سبک تر بشه و در ضمن به علت نقض گاهشماری ژولینی که از گاهشماری رومی گرفته شده بود به دستور گریگوری در تاریخ 1582 یک 10 روز از تاریخ میلادی حذف شده که نخواستم قبل این تاریخ رو لحاظ کنم . چون الگوریتم سنگین تر میشد .
و توصیه آخر : تابع 2 تا جدول متغیر داره چون با هر بار محاسبه تشکیل میشه در کارهای سریع تر بهتره که این 2 تا جدول ثابت بشن تا نرخ الگوریتم پایین بیاد .
create FUNCTION [dbo].[miladi_to_shamsi]
( @year as int , @mounth as int , @day as int )
RETURNS char(10)
BEGIN
--declare @mes as nvarchar(500)
declare @diffrent_rasmi_hesabi_kabise table (num1 int)
declare @birshak_reminder table (num1 int)
insert into @diffrent_rasmi_hesabi_kabise values (9) ,( 113 ),( 17 ),( 21 ),( 42 ),( 46 ),( 50 ),( 54 ),( 71 ),( 75 ),( 79 ),( 83 ),( 87 ),( 104 ),( 108 ),( 112 ),( 116 ),( 137 ),( 141 ),( 145 ),( 149 ),( 170 ),( 174 ),( 178 ),( 182 ),( 203 ),( 207 ),( 211 ),( 215 ),( 236 ),( 240 ),( 244 ),( 269 ),( 273 ),( 277 ),( 302 ),( 306 ),( 310 ),( 331 ),( 335 ),( 339 ),( 343 ),( 364 ),( 368 ),( 372 ),( 397 ),( 401 ),( 405 ),( 430 ),( 434 ),( 438 ),( 463 ),( 467 ),( 471 ),( 475 ),( 496 ),( 500 ),( 504 ),( 529 ),( 533 ),( 537 ),( 558 ),( 562 ),( 566 ),( 570 ),( 591 ),( 595 ),( 599 ),( 603 ),( 924 ),( 628 ),( 632 ),( 661 ),( 665 ),( 690 ),( 694 ),( 698 ),( 723 ),( 727 ),( 731 ),( 756 ),( 760 ),( 789 ),( 793 ),( 822 ),( 824 ),( 855 ),( 859 ),( 888 ),( 921 ),( 954 ),( 983 ),( 987 ),( 1016 ),( 1049 ),( 1082 ),( 1115 ),( 1243 ),( 1275 ),( 1308 ),( 1341 ),( 1403 ),( 1436 ),( 1469 ),( 1473 ),( 1502)
insert into @birshak_reminder values (0 ),( 4 ),( 8 ),(12 ),(16 ),( 20 ),( 24 ),( 29 ),( 33 ),( 37 ),( 41 ),( 45 ),( 49 ),( 53 ),( 57 ),( 62 ),( 66 ),( 70 ),( 74 ),( 78 ),( 82 ),( 86 ),( 90 ),( 95 ),( 99 ),( 103 ),( 107 ),( 111 ),( 115 ),( 119 ),( 124)
--insert into @birshak_reminder_less_than_474 values ( 25) ,( 58 ), ( 91) , ( 120)
declare @kabise_milady as int,@kabise_milady_1 as int ,@kabise_shamsi as int
select @kabise_milady_1= case when case when (case when (@year-1)%100 =0 then 0 else 1 end)=0 then (@year-1)%400 else ( @year-1)%4 end =0 then 1 else 0 end
if @kabise_milady_1=1 select @kabise_milady=0 else select @kabise_milady= case when case when (case when @year %100 =0 then 0 else 1 end)=0 then @year %400 else @year %4 end =0 then 1 else 0 end
select @year = @year-622
select @kabise_shamsi= count(*) from @diffrent_rasmi_hesabi_kabise where num1= @year
if @kabise_shamsi <>1 select @kabise_shamsi= count(*) from @birshak_reminder where num1= (@year%128)
select @day =
case @mounth
when 1 then 0 --31
when 2 then 31 --28 or 29
when 3 then 59 +@kabise_milady--31
when 4 then 90+@kabise_milady --30
when 5 then 120+@kabise_milady --31
when 6 then 151+@kabise_milady --30
when 7 then 181+@kabise_milady --31
when 8 then 212+@kabise_milady --31
when 9 then 243+@kabise_milady --30
when 10 then 273+@kabise_milady --31
when 11 then 304+@kabise_milady --30
when 12 then 334 +@kabise_milady--31
end +@day
--select @mes=' - kabise_milady='+cast(@kabise_milady as nvarchar) +' -kabise_shamsi:'+cast(@kabise_shamsi as nvarchar) + '-day= '+cast(@day as nvarchar) +' - '
if @day>79+@kabise_milady
begin
select @year =@year+1
select @day =@day-79
end
else
select @day =@day+286+@kabise_milady_1
if @day=365 select @day=365+ @kabise_shamsi
--select @mes=@mes+' shamsi day='+cast(@day as nvarchar) +' - '
select @mounth=case when @day> 186 then (@day-187) /30 +7 else (@day-1) /31 +1 end
select @day=case when @day> 186 then (@day-187) %30+1 else (@day-1) %31 +1 end
return -- @mes +
cast(@year as char(4)) + case when @mounth<10 then '/0'+ cast( @mounth as nvarchar(1)) else '/'+ cast( @mounth as nvarchar(2)) end + case when @day<10 then '/0'+ cast( @day as nvarchar(1)) else '/'+ cast( @day as nvarchar(2)) end
END
سعی کردم از سال ۴۷۴ به بعد باشه تا الگوریتم سبک تر بشه و در ضمن به علت نقض گاهشماری ژولینی که از گاهشماری رومی گرفته شده بود به دستور گریگوری در تاریخ 1582 یک 10 روز از تاریخ میلادی حذف شده که نخواستم قبل این تاریخ رو لحاظ کنم . چون الگوریتم سنگین تر میشد .
و توصیه آخر : تابع 2 تا جدول متغیر داره چون با هر بار محاسبه تشکیل میشه در کارهای سریع تر بهتره که این 2 تا جدول ثابت بشن تا نرخ الگوریتم پایین بیاد .
create FUNCTION [dbo].[miladi_to_shamsi]
( @year as int , @mounth as int , @day as int )
RETURNS char(10)
BEGIN
--declare @mes as nvarchar(500)
declare @diffrent_rasmi_hesabi_kabise table (num1 int)
declare @birshak_reminder table (num1 int)
insert into @diffrent_rasmi_hesabi_kabise values (9) ,( 113 ),( 17 ),( 21 ),( 42 ),( 46 ),( 50 ),( 54 ),( 71 ),( 75 ),( 79 ),( 83 ),( 87 ),( 104 ),( 108 ),( 112 ),( 116 ),( 137 ),( 141 ),( 145 ),( 149 ),( 170 ),( 174 ),( 178 ),( 182 ),( 203 ),( 207 ),( 211 ),( 215 ),( 236 ),( 240 ),( 244 ),( 269 ),( 273 ),( 277 ),( 302 ),( 306 ),( 310 ),( 331 ),( 335 ),( 339 ),( 343 ),( 364 ),( 368 ),( 372 ),( 397 ),( 401 ),( 405 ),( 430 ),( 434 ),( 438 ),( 463 ),( 467 ),( 471 ),( 475 ),( 496 ),( 500 ),( 504 ),( 529 ),( 533 ),( 537 ),( 558 ),( 562 ),( 566 ),( 570 ),( 591 ),( 595 ),( 599 ),( 603 ),( 924 ),( 628 ),( 632 ),( 661 ),( 665 ),( 690 ),( 694 ),( 698 ),( 723 ),( 727 ),( 731 ),( 756 ),( 760 ),( 789 ),( 793 ),( 822 ),( 824 ),( 855 ),( 859 ),( 888 ),( 921 ),( 954 ),( 983 ),( 987 ),( 1016 ),( 1049 ),( 1082 ),( 1115 ),( 1243 ),( 1275 ),( 1308 ),( 1341 ),( 1403 ),( 1436 ),( 1469 ),( 1473 ),( 1502)
insert into @birshak_reminder values (0 ),( 4 ),( 8 ),(12 ),(16 ),( 20 ),( 24 ),( 29 ),( 33 ),( 37 ),( 41 ),( 45 ),( 49 ),( 53 ),( 57 ),( 62 ),( 66 ),( 70 ),( 74 ),( 78 ),( 82 ),( 86 ),( 90 ),( 95 ),( 99 ),( 103 ),( 107 ),( 111 ),( 115 ),( 119 ),( 124)
--insert into @birshak_reminder_less_than_474 values ( 25) ,( 58 ), ( 91) , ( 120)
declare @kabise_milady as int,@kabise_milady_1 as int ,@kabise_shamsi as int
select @kabise_milady_1= case when case when (case when (@year-1)%100 =0 then 0 else 1 end)=0 then (@year-1)%400 else ( @year-1)%4 end =0 then 1 else 0 end
if @kabise_milady_1=1 select @kabise_milady=0 else select @kabise_milady= case when case when (case when @year %100 =0 then 0 else 1 end)=0 then @year %400 else @year %4 end =0 then 1 else 0 end
select @year = @year-622
select @kabise_shamsi= count(*) from @diffrent_rasmi_hesabi_kabise where num1= @year
if @kabise_shamsi <>1 select @kabise_shamsi= count(*) from @birshak_reminder where num1= (@year%128)
select @day =
case @mounth
when 1 then 0 --31
when 2 then 31 --28 or 29
when 3 then 59 +@kabise_milady--31
when 4 then 90+@kabise_milady --30
when 5 then 120+@kabise_milady --31
when 6 then 151+@kabise_milady --30
when 7 then 181+@kabise_milady --31
when 8 then 212+@kabise_milady --31
when 9 then 243+@kabise_milady --30
when 10 then 273+@kabise_milady --31
when 11 then 304+@kabise_milady --30
when 12 then 334 +@kabise_milady--31
end +@day
--select @mes=' - kabise_milady='+cast(@kabise_milady as nvarchar) +' -kabise_shamsi:'+cast(@kabise_shamsi as nvarchar) + '-day= '+cast(@day as nvarchar) +' - '
if @day>79+@kabise_milady
begin
select @year =@year+1
select @day =@day-79
end
else
select @day =@day+286+@kabise_milady_1
if @day=365 select @day=365+ @kabise_shamsi
--select @mes=@mes+' shamsi day='+cast(@day as nvarchar) +' - '
select @mounth=case when @day> 186 then (@day-187) /30 +7 else (@day-1) /31 +1 end
select @day=case when @day> 186 then (@day-187) %30+1 else (@day-1) %31 +1 end
return -- @mes +
cast(@year as char(4)) + case when @mounth<10 then '/0'+ cast( @mounth as nvarchar(1)) else '/'+ cast( @mounth as nvarchar(2)) end + case when @day<10 then '/0'+ cast( @day as nvarchar(1)) else '/'+ cast( @day as nvarchar(2)) end
END