SabaSabouhi
سه شنبه 05 اسفند 1393, 08:39 صبح
سلام
چون دوستان زیادی دنبال تابع تبدیل تاریخ میلادی به شمسی میگشتن من این تابع رو مجدد ارسال میکنم. چون ارسال قبلی مربوط به چند سال
پیش و داخل یه تاپیک طولانی بود و تو جستجو راحت پیدا نمیشد، دوباره میفرستم به این امید که به درد دوستان بخوره.
1. تو این UDF غیر از DATEPART از هیچ تابعی استفاده نشده ( برای حداکثر سرعت )
2. هیچ حلقهای وجود نداره
3. الگوریتم محاسبه شکسته شده، ( با خوندن متن شاید متوجه منطق برنامه نشین )
4. تو تمام دامنه تعریف یعنی از سال 1900 تا 2100 میلادی ( محدودهی SmallDateTime ) تست شده
5. این رو حدود 15 سال پیش نوشتم، اما هنوز هیچ تابعی سریعتر و بهینهتر از این ندیدم.
6. لایسنس از کد Free هست. استفاده کنید و به دوستانتون هم بدین.
CREATE FUNCTION [dbo].[SDate]( @Date as SmallDateTime)
RETURNS int
AS
BEGIN
-- Convert English Calendar to Persian Calendar
-- Created by Saba Sabouhi
DECLARE @Year as int, @Month as int, @Day as int
DECLARE @Year2 as int, @Month2 as int, @Day2 as int
DECLARE @Period as int
DECLARE @pIdx as int, @MonLen as int
DECLARE @n as int
SET @Year = DatePart( yyyy, @Date)
SET @Month = DatePart( m, @Date)
SET @Day = DatePart( d, @Date)
IF @Year < 1970
SET @Period = (@Year - 1897) / 32
ELSE
SET @Period = (@Year - 1897 - 4) / 32
SET @pIdx = (@Year - 1) - 4 * ((@Year - 1) / 4)
SET @Day2 = @Day + CASE
WHEN @Month in (1, 5, 6) THEN 10
WHEN @Month in (2, 4) THEN 11
WHEN @Month in (3, 7, 8, 9, 11, 12) THEN 9
WHEN @Month = 10 THEN 8 END
SET @Day2 = @Day2 - CASE
WHEN @Period < @pIdx - 1 THEN 1
WHEN @Period > @pIdx + 2 THEN -1
ELSE 0 END
SET @MonLen = CASE
WHEN @Month in (1, 2, 10, 11, 12) THEN 30
WHEN @Month = 3 THEN 29
ELSE 31 END
IF @Month > 2 AND @Year = 4 * (@Year / 4)
SET @Day2 = @Day2 + 1
SET @n = (@Year - 1899) - 33 * ( (@Year - 1899) / 33 )
IF @n in (3, 7, 11, 15, 19, 23, 27, 32)
BEGIN
IF @Month > 3
SET @Day2 = @Day2 - 1
IF @Month = 3
SET @MonLen = @MonLen + 1
END
SET @n = @Month
IF @Date < '1900/3/1'
SET @Day2 = @Day2 + 1
IF @Day2 > @MonLen
SET @Day2 = @Day2 - @MonLen
ELSE
SET @n = @n - 1
SET @Month2 = 1 + ( @n + 9 ) - 12 * (( @n + 9) / 12)
IF @Month2 > @Month
SET @Year2 = @Year - 622
ELSE
SET @Year2 = @Year - 621
RETURN @Year2 * 10000 + @Month2 * 100 + @Day2
END
صبا صبوحی
چون دوستان زیادی دنبال تابع تبدیل تاریخ میلادی به شمسی میگشتن من این تابع رو مجدد ارسال میکنم. چون ارسال قبلی مربوط به چند سال
پیش و داخل یه تاپیک طولانی بود و تو جستجو راحت پیدا نمیشد، دوباره میفرستم به این امید که به درد دوستان بخوره.
1. تو این UDF غیر از DATEPART از هیچ تابعی استفاده نشده ( برای حداکثر سرعت )
2. هیچ حلقهای وجود نداره
3. الگوریتم محاسبه شکسته شده، ( با خوندن متن شاید متوجه منطق برنامه نشین )
4. تو تمام دامنه تعریف یعنی از سال 1900 تا 2100 میلادی ( محدودهی SmallDateTime ) تست شده
5. این رو حدود 15 سال پیش نوشتم، اما هنوز هیچ تابعی سریعتر و بهینهتر از این ندیدم.
6. لایسنس از کد Free هست. استفاده کنید و به دوستانتون هم بدین.
CREATE FUNCTION [dbo].[SDate]( @Date as SmallDateTime)
RETURNS int
AS
BEGIN
-- Convert English Calendar to Persian Calendar
-- Created by Saba Sabouhi
DECLARE @Year as int, @Month as int, @Day as int
DECLARE @Year2 as int, @Month2 as int, @Day2 as int
DECLARE @Period as int
DECLARE @pIdx as int, @MonLen as int
DECLARE @n as int
SET @Year = DatePart( yyyy, @Date)
SET @Month = DatePart( m, @Date)
SET @Day = DatePart( d, @Date)
IF @Year < 1970
SET @Period = (@Year - 1897) / 32
ELSE
SET @Period = (@Year - 1897 - 4) / 32
SET @pIdx = (@Year - 1) - 4 * ((@Year - 1) / 4)
SET @Day2 = @Day + CASE
WHEN @Month in (1, 5, 6) THEN 10
WHEN @Month in (2, 4) THEN 11
WHEN @Month in (3, 7, 8, 9, 11, 12) THEN 9
WHEN @Month = 10 THEN 8 END
SET @Day2 = @Day2 - CASE
WHEN @Period < @pIdx - 1 THEN 1
WHEN @Period > @pIdx + 2 THEN -1
ELSE 0 END
SET @MonLen = CASE
WHEN @Month in (1, 2, 10, 11, 12) THEN 30
WHEN @Month = 3 THEN 29
ELSE 31 END
IF @Month > 2 AND @Year = 4 * (@Year / 4)
SET @Day2 = @Day2 + 1
SET @n = (@Year - 1899) - 33 * ( (@Year - 1899) / 33 )
IF @n in (3, 7, 11, 15, 19, 23, 27, 32)
BEGIN
IF @Month > 3
SET @Day2 = @Day2 - 1
IF @Month = 3
SET @MonLen = @MonLen + 1
END
SET @n = @Month
IF @Date < '1900/3/1'
SET @Day2 = @Day2 + 1
IF @Day2 > @MonLen
SET @Day2 = @Day2 - @MonLen
ELSE
SET @n = @n - 1
SET @Month2 = 1 + ( @n + 9 ) - 12 * (( @n + 9) / 12)
IF @Month2 > @Month
SET @Year2 = @Year - 622
ELSE
SET @Year2 = @Year - 621
RETURN @Year2 * 10000 + @Month2 * 100 + @Day2
END
صبا صبوحی