# پایگاه‌های داده > SQL Server >  تاریخ میلادی رو چطوری به شمسی تبدیل کنم بوسیله sql ؟

## aki

نمیشه تاریخ میلادی رو بوسیله query توی sql تبدیل به تاریخ شمسی کرد ودر فیلد دیگری قرار داد ؟ 
ممنون میشم کمکم کنید.....

----------


## h_baqery

راه اول این است که  توابعی (UDF)  بنویسید که تاریخ میلادی رو دریافت کنند و تاریخ شمسی رو بر گردونن و در مکانهایی که می خواهید استفاده کنید با یک view این فیلد رو به تابعتون اضافه کنید . 

این عمل باعث کندی بسیار می شود زیرا این محاسبه برای هر رکورد انجام می شود و توابع در cache قرار نمی گیرند . 

راه دیگر استفاده از یک جدول است که معادل روزهای سال را به میلادی و شمسی داشته باشد و شما با یک join با این جدول می توانید معادل شمسی رو استفاده کنید که این روش بسیار کارآمد تر است و در تجربه شخصی بنده که ده سال قبل و بعد رو در این جدول دارم بنابراین مشکل سرعت رو هم ندارم . در کاربرد این روش مزایای دیگری هم نسبت به تبدیل همزمان وجود دارد.

اگر راه اول رو بخواهید باید چند روزی صبر کنید تا متن توابع تبدیلی رو به شما بدهم ولی اگر روش دوم رو بخواهید می توانم همین حالا این جدول رو در اختیار شما قرار دهم .

----------


## SRS534

سلام من جدولی دارم که کد ایستگاهای مختلف در ان قرار دارد و جدول دیگری که دمای هر ایستگاه در ساعت ها وتاریخ های متفاوت در ان وجود دارد می خواهم با لا ترین میانگین رطوبت
هر ایستگاه راپیدا کنم میشه کمک کنید ( بدون کرسر)

----------


## h_baqery

این جدول رو با جداول دیگرتون روی فیلد تاریخ JOIN کنید .
این یک BACKUP در 2005 است و فقط در 2005 به بالا Restore می شود .

----------


## Kamyar.Kimiyabeigi

میلادی به شمسی

CREATE FUNCTION [dbo].[MiladiTOShamsi] (@MDate  DateTime)  
RETURNS Varchar(10)
AS  
BEGIN 
   DECLARE @SYear  as Integer
   DECLARE @SMonth  as Integer
   DECLARE @SDay  as Integer
   DECLARE @AllDays  as float
   DECLARE @ShiftDays  as float
   DECLARE @OneYear  as float
   DECLARE @LeftDays  as float
   DECLARE @YearDay  as Integer
   DECLARE @Farsi_Date  as Varchar(100) 
   SET @MDate=@MDate-CONVERT(char,@MDate,114)

  SET @ShiftDays=466699   +2
  SET @OneYear= 365.24199


   SET @SYear = 0
   SET @SMonth = 0
   SET @SDay = 0
   SET @AllDays  = CAst(@Mdate as Real)

   SET @AllDays = @AllDays + @ShiftDays

  SET @SYear = (@AllDays / @OneYear) --trunc
  SET @LeftDays = @AllDays - @SYear * @OneYear

  if (@LeftDays < 0.5)
  begin
    SET @SYear=@SYear+1
    SET @LeftDays = @AllDays - @SYear * @OneYear
  end;

  SET @YearDay = @LeftDays --trunc
  if (@LeftDays - @YearDay) >= 0.5 
    SET @YearDay=@YearDay+1

  if ((@YearDay / 31) > 6 )
  begin
    SET @SMonth = 6
    SET @YearDay=@YearDay-(6 * 31)
    SET @SMonth= @SMonth+( @YearDay / 30)
    if (@YearDay % 30) <> 0 
      SET @SMonth=@SMonth+1
    SET @YearDay=@YearDay-((@SMonth - 7) * 30)
  end 
  else
  begin
    SET @SMonth = @YearDay / 31
    if (@YearDay % 31) <> 0 
      SET @SMonth=@SMonth+1 
    SET @YearDay=@YearDay-((@SMonth - 1) * 31)
  end
  SET @SDay = @YearDay
  SET @SYear=@SYear+1

 SET @Farsi_Date =   CAST (@SYear   as VarChar(10)) + '/' + CAST (@SMonth   as VarChar(10)) + '/' + CAST (@SDay  as VarChar(10))
 Return @Farsi_Date



END


شمسی به میلادی

CREATE FUNCTION [dbo].[ShamsiToMiladi](@DateStr varchar(10))
RETURNS DATETIME
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 Datetime)

    END
    RETURN NULL      

END

----------


## aki

ممنون از دوستان ...
این جدول alldate رو با چی باز کنم؟

----------


## h_baqery

این یک فایل RAR باید با Winrar اونو Extract  کنید و در SQL2005 اونو Restore کنید .

----------


## sknsphr

نمی شه یه فایلی بدید که تو 2000 هم Restore بشه؟
راستی ببخشید دو تا تابع تو ShamsiToMiladi هست که SQL نمیشناسه میشه اونارو هم بدید:
dbo.ReversDate و dbo.SubStrCount
ممنون

----------


## h_baqery

backup برای 2000

----------


## h_baqery

قابل توجه است که این راه حل به ظاهر خنده دار در بسیاری از سیستمهایی که از DLL یا Function استفاده می کردند جایگزین شده به خاطر راحتی بسیار زیادی که داره و سرعت بسیار بالای اون به دلیلی که در پست دو گفتم . اگر جدول رو ببینید فیلدهای نام ماه و ... دیگر رو هم دارد و در بسیاری از گزارشات کار گزارش سازهارو ساده کرده . 
همیشه بهترین راه حرفه ای ترین و تخصصی ترین راه نیست .
شما با استفاده از تابعی که آقای کامیابی دادند و  یک cursor ساده می تونید این جدول رو تا صدها سال آینده تولید کنید و با یک join ساده هر جا که لازم است استفاده کنید حتی برای تبدیل سیستمهایی که تاریخ اصلیشون میلادیه ما با یک view و تغییر نام View به جدول مورد نظر بسیار سریع نمایش شمسی داشتیم .

----------


## linux

خسته نباشی دستاتو بشور.
یادت باشه برای همیشه! بهترین راه حل تخصصی ترین راه حل هست.
اولا تاریخ در sql server بصورت یک عدد 8 بایتی ذخیره میشه که 4 بایت اولش روزهای گذشته از مبدا تقویم هست که در این مورد تاریخ 1/1/1900 هست و 4 بایت دوم هم میلی ثانیه های گذشته از نیمه شب را ذخیره می کند
از Ebook

*Remarks*

Values with the *datetime* data type are stored internally by Microsoft SQL Server as two 4-byte integers. The first 4 bytes store the number of days before or after the _base date_, January 1, 1900. The base date is the system reference date. Values for *datetime* earlier than January 1, 1753, are not permitted. The other 4 bytes store the time of day represented as the number of milliseconds after midnight.

این دستورات را اجرا کنید تا دقیقا بفهمید منظور چی هست

go
select getdate()
go
select cast(getdate() as float)

جواب بصورت 

                                                       
------------------------------------------------------ 
2006-09-28 00:32:42.000
(1 row(s) affected)
                                                      
----------------------------------------------------- 
38986.022708487653
(1 row(s) affected)

خواهد بود یعنی sql server موقع نمایش تاریخ از یکسری توابع استفاده کرده و آن را به فرمت مورد نظر نمایش داده و در موقع ذخیره هم از یکسری توابع استفاده کرده و تاریخ مورد نظر را بصورت یک عدد 8 بایتی ذخیره می کند.
حالا اگر شما مستقیما این عدد را به تاریخ شمسی تبدیل کنید همان زمان که sqlserver جهت تبدیل استفاده می کند شما هم استفاده خواهید کرد.
و توابع که شما اینجا گذاشتید هیچ کدام این کار را انجام نمی دهند.برای همین یک خورده کند هست

----------


## احمد سامعی

> خسته نباشی دستاتو بشور.
> یادت باشه برای همیشه! بهترین راه حل تخصصی ترین راه حل هست.


ببخشید دوستان از دعوا و جار و جنجال گذشته ...
می شه یک کد کامل یا یک راه حل کامل بگید تا ما هم بفهمیم آخرش چی کار باید کرد
من از کنترل فارسی لایبری که در سایت کدپرژکت هست استفاده کردم و فقط مقدار بازگشتی میلادی و برای نشون دادن به کاربر و سرچ توسط اون بر مبنای تاریخ و گذارش گیری مشکل دارم می شه بگید چطور تبدیل کنیم
یکی از دوستان یک کلاس نوشته بود اما من لینکش رو پیدانکردم

----------


## linux

ببینید کلا 2 روش وجود داره یکی در سطح برنامه که من موقع ورود اطلاعات از این کار استفاده می کنم یعنی مثلا تاریخ را بصورت شمسی از کاربر می گیرم ولی بصورت میلادی در بانکدادهها ذخیره می کنم.
راه دوم در سطح خود sql سرور که توابعی را که دارم بکار میبرم.
توابع را در پست بعدی براتون میگذارم

----------


## fan2005

سلام،
من یک تازه کار هستم.اگه میشه لطفا در مورد این جدول alldate بیشتر توضیح دهید .
طرز استفاده از آن را در محیط .net2005 را قم به قدم توضیح دهید.
ممنون می شویم.

----------


## aki

alldate یک backup از یک database در sql هست . باید restore بشه . . .

----------


## linux

DROP FUNCTION dbo.Persian2Civil
DROP FUNCTION dbo.Civil2Persian
DROP FUNCTION dbo.IsPersianLeapYear
DROP FUNCTION dbo.persian_jdn
DROP FUNCTION dbo.jdn_persian
DROP FUNCTION dbo.Ceil
DROP FUNCTION dbo.Mmod
GO
CREATE FUNCTION dbo.Persian2Civil(@year int, @month int, @day int)
RETURNS char(10) AS
BEGIN
RETURN dbo.jdn_civil(dbo.persian_jdn(@year, @month, @day))
END
GO
CREATE FUNCTION dbo.Civil2Persian(@CivilDate smalldatetime)
RETURNS char(10) AS
BEGIN
RETURN dbo.jdn_persian(CAST(@CivilDate as bigint)+2415021)
--RETURN dbo.jdn_persian(dbo.civil_jdn(@year, @month, @day))
END
GO
CREATE FUNCTION dbo.IsPersianLeapYear (@iYear bigint)
RETURNS bigint AS  
BEGIN 
DECLARE @temp bigint
DECLARE @lp bit
IF @iYear > 0
 SET @temp = ((((dbo.MMod((@iYear - (474)), 2820) + 474) + 38) * 682) % 2816)
ELSE
 SET @temp =  ((((dbo.MMod((@iYear - (473)), 2820) + 474) + 38) * 682) % 2816)
IF @temp < 682
 SET @lp = 1
ELSE
 SET @lp = 0
RETURN @lp
END
 
GO
CREATE FUNCTION dbo.persian_jdn(@iYear bigint, @iMonth int, @iDay int)
RETURNS bigint AS  
BEGIN 
DECLARE @PERSIAN_EPOCH bigint
SET @PERSIAN_EPOCH = 1948321 -- The JDN of 1 Farvardin 1
DECLARE @epbase bigint
DECLARE @epyear bigint
DECLARE @mdays bigint
DECLARE @temp bigint
IF @iYear >= 0
 SET @epbase = @iYear - 474
ELSE
 SET @epbase = @iYear - 473

SET @epyear = 474 + dbo.MMod(@epbase, 2820)
IF @iMonth <= 7
 SET @mdays = (@iMonth - 1) * 31
ELSE
 SET @mdays = (@iMonth - 1) * 30 + 6

SET @temp = @iDay + @mdays + CAST(((@epbase / 2820) * 1029983 + (@PERSIAN_EPOCH - 1)) AS bigint)
RETURN @temp + CAST(((((@epyear * 682) - 110) / 2816) + (@epyear - 1) * 365) AS bigint)
END
GO
CREATE FUNCTION dbo.jdn_persian(@jdn bigint)
RETURNS char(10) AS  
BEGIN 
DECLARE @depoch bigint
DECLARE @cycle int
DECLARE @cyear bigint
DECLARE @ycycle int
DECLARE @aux1 int, @aux2 int
DECLARE @yday int
DECLARE @iYear bigint, @iMonth int, @iDay int
DECLARE @tmpMonth char(2),@tmpDay char(2)
SET @depoch = @jdn - dbo.persian_jdn(475, 1, 1)
SET @cycle = CAST((@depoch / 1029983) AS int)
SET @cyear = dbo.MMod(@depoch, 1029983)
IF @cyear = 1029982
 SET @ycycle = 2820
ELSE
BEGIN
 SET @aux1 = CAST((@cyear / 366) AS int)
 SET @aux2 = dbo.MMod(@cyear, 366)
 SET @ycycle = CAST(((((2134 * @aux1) + (2816 * @aux2) + 2815) / 1028522)) AS int) + @aux1 + 1
END
SET @iYear = @ycycle + (2820 * @cycle) + 474
IF @iYear <= 0
 SET @iYear = @iYear - 1
SET @yday = (@jdn - dbo.persian_jdn(@iYear, 1, 1)) + 1
IF @yday <= 186
 SET @iMonth = dbo.Ceil(CAST(@yday AS float)/ 31)
ELSE
 SET @iMonth = dbo.Ceil(CAST((@yday - 6) AS float)/ 30)
SET @iDay = (@jdn - dbo.persian_jdn(@iYear, @iMonth, 1)) + 1
IF @iMonth < 10 
 SET @tmpMonth= N'0'+ CAST( @iMonth as char(2))
ELSE
 SET @tmpMonth =CAST( @iMonth as char(2))
IF @iDay < 10 
 SET @tmpDay= N'0'+ CAST( @iDay as char(2))
ELSE
 SET @tmpDay =CAST( @iDay as char(2))
RETURN CAST(@iYear AS char(4)) + N'/' + @tmpMonth   + N'/' + @tmpDay
END
GO
CREATE FUNCTION dbo.Ceil(@number float)
RETURNS bigint AS  
BEGIN 
RETURN CASE SIGN(@number) WHEN -1 THEN CEILING(@number) - 1 ELSE CEILING(@number) END
END
GO
CREATE FUNCTION dbo.MMod (@numerator bigint, @denominator bigint)
RETURNS bigint AS  
BEGIN 
 RETURN ((@numerator % @denominator) + @denominator) % @denominator
END
 
GO
 


البته بهتر از این هم میشد کدها را نوشت فعلا این را داشته باشید

----------


## محمد دادودنیا

آقای Linux‌پر مدعا لطف کنید در حد تخصص تان از تخصصی بودن صحبت کنید
1-اگر نظری دارید بدون توهین اعلام کنید
2-نظر های خوب دیگران را قبول کنید
3-ببینید واقعا راست می گویید یا ار سر بغض 
و...

ولی در حال کدی که نوشته اید به خاطر چند تابعی بودن سرعت رو بسیار کند می کنه مخصوصا اگر در Veiw‌با تعداد رکورد بالا استفاده بشه باید ...................
ولی این تابع با سرعت بهتری کار می کنه



> Create      Function AFf_MiladyToShamsi(@d int,@m int,@y int)
> Returns NvarChar(10) AS
> begin
> -- Convert Milady to Shamsi
> -- Update By Written By Mohammad Davoodnia 
> -- All Rigth Reserved AFTABGARDAN(C) 1385
> Declare @ny as int
> Declare @nd as int
> Declare @nm as int
> ...


ضمنا SQL Server به خاطر اینکه در مدیریت Proc و Func ضعیف عمل می کنه سرعت کار با توابع و پروسیجرها بسیار کنده

----------


## linux

> آقای Linux‌پر مدعا لطف کنید در حد تخصص تان از تخصصی بودن صحبت کنید
> 1-اگر نظری دارید بدون توهین اعلام کنید
> 2-نظر های خوب دیگران را قبول کنید
> 3-ببینید واقعا راست می گویید یا ار سر بغض 
> و...
> 
> ولی در حال کدی که نوشته اید به خاطر چند تابعی بودن سرعت رو بسیار کند می کنه مخصوصا اگر در Veiw‌با تعداد رکورد بالا استفاده بشه باید ...................
> ولی این تابع با سرعت بهتری کار می کنه
> 
> ضمنا SQL Server به خاطر اینکه در مدیریت Proc و Func ضعیف عمل می کنه سرعت کار با توابع و پروسیجرها بسیار کنده


:)
ببین عمو جون من نظرم را هر جوری دلم بخواهد اعلام می کنم. حالا بعضی ها زود به خودشان می گیرند. اخه من با شما ها چه بغضی دارم؟! اینجا نه به کسی پول می دهند نه قرار هست به کد کسی جایزه بدهند من اگر اینجا یک کدی قرار می دهم در برنامه هام ازش استفاده می کنم و به درست بودنش هم مطمئن هستم و تست شده می گذارم اینجا که مشکل یک عده مثل شما ها حل بشود اجبار هم نیست که شما از این کدها استفاده کنید یا از روشهای و کدهای خودتان.
این کد شما هم اشتباه هست هیچ جای کدتان برای سال کبیسه محاسباتی انجام نداده اید. بهتر هست توی تقویم روزهای 2005/3/19 و 2004/3/19 و 2004/3/20 و 2004/3/21 را ببنید که چه روزی بوده و بعد با برنامه خودتان چک کنید و همچنین برای سال 2008 همین روزها را چک کنید.

من کد خودم را با 200 هزار رکورد هم اجرا کردم و در عمل هیچ تاخیری و مشکلی ندیدم.

----------


## SQLPRO

با سلام
یکی از شیوه های که در برنامه هام ازش استفاده کردم و راضی هم بودم استفاده از دو ستون  برای تاریخ بود. اولی تایخ شمسی که از نوع CHar 10 بود و دومی تاریخ میلادی و از جنس DateTime.
 در جاهایی که میخواستم تاریخ شمسی رو نمایش بدم از ستون تاریخ شمسی استفاده میکردم و برای جاهایی که نیاز به محاسبه روی تاریخ داشتم  از ستون تاریخ میلادی استفاده میکردم.
در این روش تبدیلات عموما" فقط در هنگام ثبت اطلاعات بود و هنگام کوئری گرفتن تنها با یک اسکن روی اندیکس ها  و بدون تبدیلات اطلاعات نمایش داده میشد که سرعت مناسبی رو هم هنگام کار داشتم. 
امیدوارم این شیوه مورد توجه دوستان قرار بگیرد.
*( دوستانی که با این شیوه مخالف هستند لطف کنند نظرشون رو با دلیل بیان کنند . با تشکر)*
خدا یار و نگهدارتان باشد.

----------


## محمد دادودنیا

> :)
> ببین عمو جون من نظرم را هر جوری دلم بخواهد اعلام می کنم. حالا بعضی ها زود به خودشان می گیرند. اخه من با شما ها چه بغضی دارم؟! اینجا نه به کسی پول می دهند نه قرار هست به کد کسی جایزه بدهند من اگر اینجا یک کدی قرار می دهم در برنامه هام ازش استفاده می کنم و به درست بودنش هم مطمئن هستم و تست شده می گذارم اینجا که مشکل یک عده مثل شما ها حل بشود اجبار هم نیست که شما از این کدها استفاده کنید یا از روشهای و کدهای خودتان.
> این کد شما هم اشتباه هست هیچ جای کدتان برای سال کبیسه محاسباتی انجام نداده اید. بهتر هست توی تقویم روزهای 2005/3/19 و 2004/3/19 و 2004/3/20 و 2004/3/21 را ببنید که چه روزی بوده و بعد با برنامه خودتان چک کنید و همچنین برای سال 2008 همین روزها را چک کنید.
> 
> من کد خودم را با 200 هزار رکورد هم اجرا کردم و در عمل هیچ تاخیری و مشکلی ندیدم.
> به هر حال شما همچنان می توانید از توابع اشتباه خودتان استفاده کنید و فکر کنید که خیییییلی متخصص هستید. 
> بابا متخصص! منتظر تشکر شما برای راهنمایی که شما را کردم هستم. به هر حال کدتان و خودتان وقتم را گرفتید.


D:
حالشو ببر

----------


## linux

> D:
> حالشو ببر


پسر خوب گفتم برو تقویم را نگاه کن! 
19 مارس 2008 برابر 29 اسفند 1386 خواهد بود نه 28 اسفند!
http://www.minelinks.com/calendar_converter.html
از اینجا نگاه کن
 و اینجا 
http://www.fourmilab.ch/documents/calendar/

سال 2008 سال کبیسه هست.
اگر فکر می کنی کسایی که این سایت را اداره می کنند برنامه اشتباه برای تبدیل این تاریخ را نوشته اند حتما با آنها تماس بگیر و راهنمایشان کن. خیلی خوشحال خواهند شد که  متخصصی مثل شما به سایتشان سرزده است.

----------


## اَرژنگ

> با سلام
> یکی از شیوه های که در برنامه هام ازش استفاده کردم و راضی هم بودم استفاده از دو ستون برای تاریخ بود. اولی تایخ شمسی که از نوع CHar 10 بود و دومی تاریخ میلادی و از جنس DateTime.
> در جاهایی که میخواستم تاریخ شمسی رو نمایش بدم از ستون تاریخ شمسی استفاده میکردم و برای جاهایی که نیاز به محاسبه روی تاریخ داشتم از ستون تاریخ میلادی استفاده میکردم.
> در این روش تبدیلات عموما" فقط در هنگام ثبت اطلاعات بود و هنگام کوئری گرفتن تنها با یک اسکن روی اندیکس ها و بدون تبدیلات اطلاعات نمایش داده میشد که سرعت مناسبی رو هم هنگام کار داشتم. 
> امیدوارم این شیوه مورد توجه دوستان قرار بگیرد.
> *( دوستانی که با این شیوه مخالف هستند لطف کنند نظرشون رو با دلیل بیان کنند . با تشکر)*
> خدا یار و نگهدارتان باشد.


والا من با هیچ روشی مخالفت ندارم ، ولی این روش یکی از اصول را میشکنه، اسماً اولین نرمال فرم.
در اولین نرمال فرم هیچ داتایی دوبار نباید تکرار شده باشه.
دومین اشکالش هم اینه که یک داتا را دو جا نگهداری میکنه، اگچه بر طبقه گفته شما هیچ وقت این تاریخ عوض نمیشه، ولی داشتن کپی از یک داتا در سیستم خلاف اصوله مهندسی  سیستم است.

----------


## محمد دادودنیا

> پسر خوب گفتم برو تقویم را نگاه کن! 
> 19 مارس 2008 برابر 29 اسفند 1386 خواهد بود نه 28 اسفند!
> http://www.minelinks.com/calendar_converter.html
> از اینجا نگاه کن
> و اینجا 
> http://www.fourmilab.ch/documents/calendar/
> 
> سال 2008 سال کبیسه هست.
> اگر فکر می کنی کسایی که این سایت را اداره می کنند برنامه اشتباه برای تبدیل این تاریخ را نوشته اند حتما با آنها تماس بگیر و راهنمایشان کن. خیلی خوشحال خواهند شد که متخصصی مثل شما به سایتشان سرزده است.


البته که اینطوره ولی قبل از من متخصصی مثل شما سر زده فکر کنم بیشتر خوشحال شدن
ضمنا بعدیش رو هم داشته باش

----------


## linux

> البته که اینطوره ولی قبل از من متخصصی مثل شما سر زده فکر کنم بیشتر خوشحال شدن
> ضمنا بعدیش رو هم داشته باش


من که نمی خواهم باشما کل بندازم که! دارم می گم که محاسبات شما اشتباه هست.
عکس قبلی که مال بیمه آسیا بود انداختی روز 19 مارس 2008 را برابر 28 اسفند 1386 محاسبه کرده که این اشتباه هست.
رفتی برای من عکس گرفتی از سایت که چی بشه؟  موقع تبدیل تاریخ ها هم باید محاسبات برای سال کبیسه شمسی را درنظر بگیری و هم برای سالهای کبیسه میلادی.
حالا در این دو عکس. که فرستادی 28 اسفند 1386 برابر است با 18 مارس 2008 ولی با تقویم شما این روز را 27 اسفند محاسبه می کند دلیلش بخاطر این هست که سال 2008 سال کبیسه هست.
1 فروردین 1387 برابر با 20 مارس 2008 هست که در تابع شما این روز را 29 اسفند 1386 محاسبه می کنه. من فکر کنم اصلا از نحوه کار این سایتی که لینک دادم سردر نیاوردی!
برو یک بار تبدیل این روزها را به هم از این سایت نگاه کن یک بار هم با برنامه خودت محاسبه کن وقتی متوجه اشتباه خودت شدی حتما یادت باشه که در ضمن اینکه تشکر باید کنی! یک معذرت خواهی به تمام کسانیکه این پست را خوانده اند بدهکار هستی.

----------


## JavanSoft

البته بحثهای شما بسیار زیبا و اموزنده بود 
(بجز برخی قسمتهایی که دیگران را مورد لطف قرار داده بودید)

اما خدمتتان عرض کنم بنده از 2000 استفاده می کنم و 3 سال پیش نیز برای تاریخهای شمسی کارکتر 10 را استفاده نمودم برای محاسبات تفاضل تاریخ و فواصل و اشتراکها در UI نیز از یک کامپوننت تولید شده توسط شرکت خودمان استفاده کردم که به رایگان نیز در همین سایت قرار داده شد 
اما بخش مهم در مورد همین محاسبات در 2000 بود که نه تنها تاریخ های معادل فارسی را نگهداری می کردم که جدول تاریخ را نیز ایجاد و بایک برنامه خیلی ساده انرا پر نموده و از روش Join استفاده کردم

در نهایت اینکه سرعت بازیابی تاریخ های معادل از جدول همواره پایین تراز بدترین الگوریتم محاسبه است و این توابعی که دوستان قید فرمودند 
1- در مورد انچه دوست عزیز Linuxگذاشته بودند تابع jdn_civil رو فراموش کردند قرار دهند بنابراین نتوانستم تست را انجام دهم
2- در مورد انچه دوست عزیز kamyarفرمودند تابع Substrcount وجود ندارد 

امیدوارم دوستان عزیز در مورد این بحث بصورت جدی راه حل ارائه نمایند

----------


## محمد دادودنیا

سال 2008 ‌سال کبیسه نیست
در ضمن نیازی به تشکر یا مغذرت نیست اگر بدونم تابع ام اشتباه است اونو بررسی می کنم و دوباره اصلاحش می کنم ولی از همه دوستانی که توابع رو تست می کنن تشکر می کنم

----------


## SQLPRO

> والا من با هیچ روشی مخالفت ندارم ، ولی این روش یکی از اصول را میشکنه، اسماً اولین نرمال فرم.
> در اولین نرمال فرم هیچ داتایی دوبار نباید تکرار شده باشه.
> دومین اشکالش هم اینه که یک داتا را دو جا نگهداری میکنه، اگچه بر طبقه گفته شما هیچ وقت این تاریخ عوض نمیشه، ولی داشتن کپی از یک داتا در سیستم خلاف اصوله مهندسی  سیستم است.


 با سلام خدمت ارژنگ خان
حرفی که شما گفتید 100 درصد درست هست. ولی یک چیز رو من تو دیتابیس یاد گرفتم و از قوانین هم هست که برای بالا بردن پرفرمنس میتونیم دیتابیس رو DeNormalize کنیم. 
یه جورایی( دلیل منطقی نیست ولی یه جورایی) این کارای ما برای ذخیره تاریخ شمسی و سرچ و سورت و .. بر روی آن  برا ی SQL Server غیر منطقیه در حالی که ما بهش نیاز داریم. حالا که ما به این مهم نیاز داریم مجبوریم که کارهایی رو انجام بدیم. مثلا" استفاده از همین توابعی که  دوستان در صدد  پیاد سازی آن هستند. اگر بخواهیم پرفرمنس رو برای این توابع در برابر این شیوه که استفاده کرده ام  مقایسه کنیم توابع دوستان پرفرمنس پایین تری خواهند داشت در حالی که میشه گفت اونها اصل رو رعایت کرده اند.
درضمن دوست من مگر این یک ستون چقدر جا خواهد گرفت؟ اگر ما در دیتا بیس های امروزی بخواهیم اینقدر نگران حجم باشیم  بهتر است که ایندکس نسازیم و بگیوییم پرفرمنس بیایید پایین در عین حالی که حجم دیتابیس هم میایید پایین.
حالا بازم خوشحال میشوم نظر شما را در این موارد بدانم.
(همیشه مجادله علمی باعث بالا رفتن بحث میشود ولی درصورتی که ادب در آن رعایت شود و کسی دیگر را به خاطر اشتباه و یا پایین بودن علمش مورد تمسخر قرار ندهیم.)
خدا نگهدار

----------


## محمد دادودنیا

> با سلام خدمت ارژنگ خان
> درضمن دوست من مگر این یک ستون چقدر جا خواهد گرفت؟ اگر ما در دیتا بیس های امروزی بخواهیم اینقدر نگران حجم باشیم بهتر است که ایندکس نسازیم و بگیوییم پرفرمنس بیایید پایین در عین حالی که حجم دیتابیس هم میایید پایین.
> 
> (همیشه مجادله علمی باعث بالا رفتن بحث میشود ولی درصورتی که ادب در آن رعایت شود و کسی دیگر را به خاطر اشتباه و یا پایین بودن علمش مورد تمسخر قرار ندهیم.)


سلام دوست عزیر 
حرف شما یه جورایی درسته ولی همیشه بهتر بدترین حالتی  رو که ممکنه اتفاق بیفته رو  برای پیاده سازی یک پروژه در نظر بگیریم (البته نظر منه)
دوم اینکه ممکنه کاربر شما امکانات بالای نداشته باشه چه حتی الان هم هستن کسانی که با PII کار می کنن و حاضر به ارتقا هم نیستن

سوم اینکه اگه کد یا پیاده سازی شما برای امکانات پایین در نظر گرفته باشید مطمئن هستید که در امکانات بالا بهتر و سریعتر کار خواهد کرد

حرف شما درسته همیشه مجادله علمی (نه ...)باعث می شه که دقت و سرعت طراحی و کیفیت نهایی و ... بالا بره از همه کسانی هم که نقد می کنن کمال تشکر رو دارم حتی آقای Linux
ضمنا آقای Linux‌فعلا فرصت تست کردن ندارم ولی در اولین فرصت جواب درست بودن یا نبودن تابع رو براتون می فرستم البته اگر

----------


## SQLPRO

> سلام دوست عزیر 
> حرف شما یه جورایی درسته ولی همیشه بهتر بدترین حالتی  رو که ممکنه اتفاق بیفته رو  برای پیاده سازی یک پروژه در نظر بگیریم (البته نظر منه)
> دوم اینکه ممکنه کاربر شما امکانات بالای نداشته باشه چه حتی الان هم هستن کسانی که با PII کار می کنن و حاضر به ارتقا هم نیستن
> 
> سوم اینکه اگه کد یا پیاده سازی شما برای امکانات پایین در نظر گرفته باشید مطمئن هستید که در امکانات بالا بهتر و سریعتر کار خواهد کرد


با سلام
حرف شما درست است ولی گویا متوجه منظور من نشده اید. من یک قانون رو نقض کرده ام و لطلاعات اضافی نگه داری میکنم. و این کار من باعث افزایش پرفرمنس شده است. یعنی روی Pii باید جواب بده. چون منابع کمتری در مورد رم  و Cpu نیاز دارد. و فقط اندکی بیشتر به HDD یا حافظه جانبی نیاز دارد.
خدا نگهدار.

----------


## اَرژنگ

> .
> درضمن دوست من مگر این یک ستون چقدر جا خواهد گرفت؟ اگر ما در دیتا بیس های امروزی بخواهیم اینقدر نگران حجم باشیم  بهتر است که ایندکس نسازیم و بگیوییم پرفرمنس بیایید پایین در عین حالی که حجم دیتابیس هم میایید پایین


با سلام، 
من اینکه یک داتا را ۲ تا نکینیم را برایه کاهش حجم نگفتم، چونکه داشتنه یک ستون برایه این است که مبنا باشه و در همه جا فقط*به همان ستون رجاع بشه،
یکی از راه*ها که پیشنهاد شد ، داشتن یک جدوله که تمامه تاریخهایه فارسی و میلادی را داره و با یک Sql Join از اون جدول میشه  تاریخها را بهم تبدیل کرد.
مثلاٰ امروز از ۲ تا ستون استفاده میکنیم، و یادمون میمونه که  باید این ۲ ستون با هم روزبرز بشند، چند ماه بعد یک برنامه نویس جدید میاد و باید هر جا این دو ستون را باهم کار کنه، روشهایی که برنامه نویس را مجبور میکنند که این چنین چیزهایی را در مورد سیستم بدونند، در دراز مدت به جز دردسر و ایجاد باگ در سیستم به کاره دیگکه*ای نمیاند.
البته همه میگند که این حالا امروز کار کنه بسه و نگران نباشید، ولی این اصول برنامه نویسی نیست که هیچ یک چیزی را ۲ تا کنیم.

----------


## SQLPRO

> با سلام، 
> من اینکه یک داتا را ۲ تا نکینیم را برایه کاهش حجم نگفتم، چونکه داشتنه یک ستون برایه این است که مبنا باشه و در همه جا فقط*به همان ستون رجاع بشه،
> یکی از راه*ها که پیشنهاد شد ، داشتن یک جدوله که تمامه تاریخهایه فارسی و میلادی را داره و با یک Sql Join از اون جدول میشه  تاریخها را بهم تبدیل کرد.
> مثلاٰ امروز از ۲ تا ستون استفاده میکنیم، و یادمون میمونه که  باید این ۲ ستون با هم روزبرز بشند، چند ماه بعد یک برنامه نویس جدید میاد و باید هر جا این دو ستون را باهم کار کنه، روشهایی که برنامه نویس را مجبور میکنند که این چنین چیزهایی را در مورد سیستم بدونند، در دراز مدت به جز دردسر و ایجاد باگ در سیستم به کاره دیگکه*ای نمیاند.
> البته همه میگند که این حالا امروز کار کنه بسه و نگران نباشید، ولی این اصول برنامه نویسی نیست که هیچ یک چیزی را ۲ تا کنیم.


دوست عزیز شما در نظر بگیرید که این موضوع همیشه اینطور نیست. من مواقعی رو می توانم نشان بدهم که ما دوتا Sp یکسان در دیتابیس داریم که در شرایط خاصی یکیش رو ران میکنی و در شرایط خاصی دیگری را....( کمی مبحثش تخصصی است من  اینجا بازش نمیکنم) 
درضمن مگر پروژه ما داکیومنت نداره ؟ مگر همیشه باید یکی روی پروژه برنامه بنویسه؟
  مگر شخص بعدی که میاد ادمه کار بده نباید از شرایط با خبر بشه؟ 
اون برنامه نویس نمیاد بپرس این فیلد اضافی برای چیه؟ ( یا اون جدول شما برای چیه؟)  
اگر برنامه نویس ما 6 دانگ هواسش نباشه روی خیلی چیز های خطا میکنه و ...

----------


## اَرژنگ

> دوست عزیز شما در نظر بگیرید که این موضوع همیشه اینطور نیست. من مواقعی رو می توانم نشان بدهم که ما دوتا Sp یکسان در دیتابیس داریم که در شرایط خاصی یکیش رو ران میکنی و در شرایط خاصی دیگری را....( کمی مبحثش تخصصی است من  اینجا بازش نمیکنم) 
> درضمن مگر پروژه ما داکیومنت نداره ؟ مگر همیشه باید یکی روی پروژه برنامه بنویسه؟
>   مگر شخص بعدی که میاد ادمه کار بده نباید از شرایط با خبر بشه؟ 
> اون برنامه نویس نمیاد بپرس این فیلد اضافی برای چیه؟ ( یا اون جدول شما برای چیه؟)  
> اگر برنامه نویس ما 6 دانگ هواسش نباشه روی خیلی چیز های خطا میکنه و ...


مشکل هم همینه، اگر تعداد نکته‌هایی که برنامه نویس باید همیشه یادش بیاره که بتونه سیستم را گسترش بده یعنی یکجایه کار لنگه، اصول برنامه نویسی اینه که از کارهایه کارگری برنامه نویس ( یعنی کارهایی را که باید دستی انجام بده) کم کرد و حتا کاملآ  حذف کرد.
اگر که فیلد اضافی (کلمه کیلدی اینجا اضافیه) واقعآ مورد احتیاجه در آن صورت هیچ روشه دیگه‌ای نیست.
من نمیگم حتمآ باید و یا نباید قانونها رعایت بشند، البته ۱۰۰ نکته در مورد سیستم هست که فقط با درنظرگرفتنشان میشه جواب درد داد. منتها تا جایی که ممکنه ما نباید این ۱۰۰ نقطه را ۱۰۱ نقطه کنیم، هر چی که لزومات دانستن نقات از سیستم کم بشه (کسی فارسیه این را میدونه؟ Redundant Dependency and DeCoupling) سیستم محکمتر میشه. حالا هر چقدر هم داکومنتش کنند باز نداشتن یک چیزه اضافی از داشتنش بهتره.
اگر نقطه ای هست که برنامه نویس باید بدونه که با سیستم کار کنه، در اونموقع باید کاری کرد که با روشه دیگه‌ای نشه کار کرد، همان داستن پرایوت و پابلیک در برنماه نویسی برایه همان کارهاست. جذئیات را از برنامهنویس باید مخفی کرد (پرایوت)، هر چی دانستن جذئیات سیستم بیشتر بشه احتمال اینکه کسی یادش بره و یا اینکه هماهنگی سیستم  (system consistency ) بهم بخوره کمتر میشه.

اگر ممکنه کسی فارسی لغات را بگند متشکر میشم، مطمعن نیستم که معنیشان را درست میدانم.

----------


## محمد دادودنیا

با تشکر از دوستان
اگر چیزی اضافی که اضافی پس
ولی در مورد Documnet بهترین روشی که یه برنامه رو بتونی راحت به برنامه نویس دیگه ای بدی تا انجام بده ولی نکته اینجاست که چطور اونو تهیه کردی آیا ریز همه کارها و چرا این کاروکردی رو هم می نویسی یا فقط به کلیات اشاره داری(ضمنا اگه کسی روش Document نویسی خوبی بلده به ما یاد بده ممنون می شم)
البته که کنترل کردن دو تا بچه از یک بچه سخت تره حالا در هر زمینه ای که باشه فرقی نداره ولی باید دید که ایا دوتا بودن واقعا ضروریه یا نه می شه اونو اصلاح کرد.
با عرض معذرت از آقای ارزنگ عزیز اگه میشه یه کم واضحتر بگید یا ساده تر بنویسید جمله هاتون خیلی سخت خونده می شه به همون میزان هم فهمیدنش مشکله(اگه کسی Document نویس خوب بلده باشه به درت هردوتای ما می خوره)

----------


## محمد دادودنیا

> چرا دیگه معذرت، حرف درست را باید گفت، متاسفانه از این نظر من واقعاَ به کمک احتیاج دارم، تنها روشی که به کارم میاد اینه که جوابهام را کوتاه و مختصر بنویسم.


مرسی از درک بسیار زیادتون 
مختصر نویسی همیشه خوب نیست
یه چیز دیگه کدوم یکی از دوستان می تونه یه مقاله کتاب یا هر چیز دیگه از اساتید ارجمند 
1-دکتر بیژن بیرشک 
2- دکتر محمود حسابی
 در زمینه الگوریتم تبدیل تاریخ تاریخ ها (شمسی به میلادی و ...) معرفی کنه ؟
اگه آدرس کتابفروشی اشم بده منمون میشم

قابل توجه اقای Linux مثل اینکه تبدیل تاریخ جزء مباحث مسئله داره همچنین بازه زمانی قابل پیاده سازی تا این لحظه (که بدون ایراد باشه البته این نظر اساتید بسیار مهندس تر از من و شماست) کسی مدعی نشده به عنوان مثال آقای بیرشک یه تقوم 36 ساله طراحی کرده که از اونم ایراد گرفتن

----------


## problem

عنوان = گاهنامهٔ تطبیقی سه هزار ساله
مولف = احمد بیرشک (که احتمالاً معرف حضور هستند این استاد!)
ناشر = بنیاد دانشنامهٔ بزرگ فارسی
چاپ دوم سال ۱۳۷۳

از جمله صحبت‌های جالبی که در این کتاب می‌خوانید:
- مفاهیمی مثل کبیسه ۱۲۸ ساله و ...
- فرمول و جداول لازم برای تبدیل تاریخ ۱۲۶۰ تا ۲۰۰۰ ایرانی و ۱- تا ۲۰۶۲ قمری و ۶۳۹- تا ۲۶۲۱ میلادی به هم‌دیگر!
- اندکی درباره آن ۱۰ روزی که از تقویم میلادی حذف شد و هیچ معادلی در تاریخ شمسی و قمری ندارد!!
- این که چرا تقویم ایرانی (جلالی) دقیق‌ترین تقویم است، و با این وجود، هر ۱۴۱۰۰۰ سال یک روز با واقعیت اختلاف پیدا می‌کند!

----------


## problem

خطاب به linux:
اگر ممکنه کد کامل را برای ما بفرستید (کدی که قبلا فرستادید تعریف jdn_civil را نداشت.)
من خیلی مایلم که یک برنامه BenchMark بنویسم، که کارش این باشه که سه روش رو با هم مقایسه کنه، از لحاظ سرعت (و اگر سوادم رسید، از لحاظ میزان RAM و CPU مصرفی):
 - روش فانکشن‌های شما برای تبدیل تاریخ
 - روش استفاده از جدول تاریخی که Join می‌شه (به شرط بزرگی جدول، مثلاً از ۱۰۰۰ تا ۲۰۰۰ شمسی)
 - روش عدم تبدیل تاریخ در پایگاه داده، بلکه تبدیل اون در خود برنامه با کمک PersianCalendar‌ دات نت ۲
دوستان دیگه‌هم اگر روش‌های دیگه‌ای رو می‌خوان که من در این مقایسه وارد کنم، پیشنهاد بدن (اما نه پیشنهاد رو هوا، بلکه کد یا جدول لازم رو هم در اختیار بذارن.)

----------


## linux

> مرسی از درک بسیار زیادتون 
> مختصر نویسی همیشه خوب نیست
> یه چیز دیگه کدوم یکی از دوستان می تونه یه مقاله کتاب یا هر چیز دیگه از اساتید ارجمند 
> 1-دکتر بیژن بیرشک 
> 2- دکتر محمود حسابی
> در زمینه الگوریتم تبدیل تاریخ تاریخ ها (شمسی به میلادی و ...) معرفی کنه ؟
> اگه آدرس کتابفروشی اشم بده منمون میشم
> 
> قابل توجه اقای Linux مثل اینکه تبدیل تاریخ جزء مباحث مسئله داره همچنین بازه زمانی قابل پیاده سازی تا این لحظه (که بدون ایراد باشه البته این نظر اساتید بسیار مهندس تر از من و شماست) کسی مدعی نشده به عنوان مثال آقای بیرشک یه تقوم 36 ساله طراحی کرده که از اونم ایراد گرفتن


تقویم جدید از 1304 شروع میشه و قبل از آن یک محاسبه دیگری بکار می بردند که بر پایه سال 12 ماه و هر ماه 30 روز بوده که 5 روز آخر سال به آن اضافه می کردند و به آن خمسه مسترقه می گفتند و پس در هر صورت با این الگوریتم ها سال های قبل از 1304 با تقویم جور در نیم آید و بدلیل پیچیدگی محاسبات کبیسه ممکن هست که این الگوریتم ها تا یک محدوده کمی جواب بدهد ولی تقویم شما از ب بسم الله ایراد داشت.

----------


## problem

خیر در مورد ایشون چیز قابل عرضی ندارم. منظور از فانکشن شما هم *اینه*؟ اگر بعله، چون دوستان خیلی اون رو مورد لطف قرار دادن، اون رو هم وارد می‌کنم (ضمناً از لحاظ درستی تاریخی که بر می‌گردون هم مورد بررسی قرارش می‌دم که این همه بحثی که سرش شد به نتیجه برسه.)

----------


## linux

> خطاب به linux:
> اگر ممکنه کد کامل را برای ما بفرستید (کدی که قبلا فرستادید تعریف jdn_civil را نداشت.)
> من خیلی مایلم که یک برنامه BenchMark بنویسم، که کارش این باشه که سه روش رو با هم مقایسه کنه، از لحاظ سرعت (و اگر سوادم رسید، از لحاظ میزان RAM و CPU مصرفی):
> - روش فانکشن‌های شما برای تبدیل تاریخ
> - روش استفاده از جدول تاریخی که Join می‌شه (به شرط بزرگی جدول، مثلاً از ۱۰۰۰ تا ۲۰۰۰ شمسی)
> - روش عدم تبدیل تاریخ در پایگاه داده، بلکه تبدیل اون در خود برنامه با کمک PersianCalendar‌ دات نت ۲
> دوستان دیگه‌هم اگر روش‌های دیگه‌ای رو می‌خوان که من در این مقایسه وارد کنم، پیشنهاد بدن (اما نه پیشنهاد رو هوا، بلکه کد یا جدول لازم رو هم در اختیار بذارن.)


من وقتی این کد را تبدیل می کردم به sql چندتا چیز را نمیدانستم
1-تابع ieeereminder
2 تابع ceiling
در نتیجه خودم دوباره این توابع را نوشتم و در ضمن این کد را میشود اپتیمایز کرد
DROP FUNCTION dbo.Persian2Civil
DROP FUNCTION dbo.Civil2Persian
DROP FUNCTION dbo.IsPersianLeapYear
DROP FUNCTION dbo.persian_jdn
DROP FUNCTION dbo.jdn_persian
DROP FUNCTION dbo.Ceil
DROP FUNCTION dbo.Mmod
GO
CREATE FUNCTION dbo.Persian2Civil(@year int, @month int, @day int)
RETURNS char(10) AS
BEGIN
--RETURN dbo.jdn_civil(dbo.persian_jdn(@year, @month, @day))
RETURN cast(dbo.persian_jdn(@year, @month, @day) - 2415021 as 
datetime)
END
GO
CREATE FUNCTION dbo.Civil2Persian(@CivilDate smalldatetime)
RETURNS char(10) AS
BEGIN
RETURN dbo.jdn_persian(CAST(@CivilDate as bigint)+2415021)
--RETURN dbo.jdn_persian(dbo.civil_jdn(@year, @month, @day))
END
GO
CREATE FUNCTION dbo.IsPersianLeapYear (@iYear bigint)
RETURNS bigint AS  
BEGIN 
DECLARE @temp bigint
DECLARE @lp bit
IF @iYear > 0
 SET @temp = ((((dbo.MMod((@iYear - (474)), 2820) + 474) + 38) * 
682) % 2816)
ELSE
 SET @temp =  ((((dbo.MMod((@iYear - (473)), 2820) + 474) + 38) 
* 682) % 2816)
IF @temp < 682
 SET @lp = 1
ELSE
 SET @lp = 0
RETURN @lp
END
 
GO
CREATE FUNCTION dbo.persian_jdn(@iYear bigint, @iMonth int, @iDay int)
RETURNS bigint AS  
BEGIN 
DECLARE @PERSIAN_EPOCH bigint
SET @PERSIAN_EPOCH = 1948321 -- The JDN of 1 Farvardin 1
DECLARE @epbase bigint
DECLARE @epyear bigint
DECLARE @mdays bigint
DECLARE @temp bigint
IF @iYear >= 0
 SET @epbase = @iYear - 474
ELSE
 SET @epbase = @iYear - 473
 
SET @epyear = 474 + dbo.MMod(@epbase, 2820)
IF @iMonth <= 7
 SET @mdays = (@iMonth - 1) * 31
ELSE
 SET @mdays = (@iMonth - 1) * 30 + 6
 
SET @temp = @iDay + @mdays + CAST(((@epbase / 2820) * 1029983 + 
(@PERSIAN_EPOCH - 1)) AS bigint)
RETURN @temp + CAST(((((@epyear * 682) - 110) / 2816) + (@epyear - 1) * 
365) AS bigint)
END
GO
CREATE FUNCTION dbo.jdn_persian(@jdn bigint)
RETURNS char(10) AS  
BEGIN 
DECLARE @depoch bigint
DECLARE @cycle int
DECLARE @cyear bigint
DECLARE @ycycle int
DECLARE @aux1 int, @aux2 int
DECLARE @yday int
DECLARE @iYear bigint, @iMonth int, @iDay int
DECLARE @tmpMonth char(2),@tmpDay char(2)
SET @depoch = @jdn - dbo.persian_jdn(475, 1, 1)
SET @cycle = CAST((@depoch / 1029983) AS int)
SET @cyear = dbo.MMod(@depoch, 1029983)
IF @cyear = 1029982
 SET @ycycle = 2820
ELSE
BEGIN
 SET @aux1 = CAST((@cyear / 366) AS int)
 SET @aux2 = dbo.MMod(@cyear, 366)
 SET @ycycle = CAST(((((2134 * @aux1) + (2816 * @aux2) + 
2815) / 1028522)) AS int) + @aux1 + 1
END
SET @iYear = @ycycle + (2820 * @cycle) + 474
IF @iYear <= 0
 SET @iYear = @iYear - 1
SET @yday = (@jdn - dbo.persian_jdn(@iYear, 1, 1)) + 1
IF @yday <= 186
 SET @iMonth = dbo.Ceil(CAST(@yday AS float)/ 31)
ELSE
 SET @iMonth = dbo.Ceil(CAST((@yday - 6) AS float)/ 30)
SET @iDay = (@jdn - dbo.persian_jdn(@iYear, @iMonth, 1)) + 1
IF @iMonth < 10 
 SET @tmpMonth= N'0'+ CAST( @iMonth as char(2))
ELSE
 SET @tmpMonth =CAST( @iMonth as char(2))
IF @iDay < 10 
 SET @tmpDay= N'0'+ CAST( @iDay as char(2))
ELSE
 SET @tmpDay =CAST( @iDay as char(2))
RETURN CAST(@iYear AS char(4)) + N'/' + @tmpMonth   + N'/' + @tmpDay
END
GO
CREATE FUNCTION dbo.Ceil(@number float)
RETURNS bigint AS  
BEGIN 
RETURN CASE SIGN(@number) WHEN -1 THEN CEILING(@number) - 1 
ELSE CEILING(@number) END
END
GO
CREATE FUNCTION dbo.MMod (@numerator bigint, @denominator bigint)
RETURNS bigint AS  
BEGIN 
 RETURN ((@numerator % @denominator) + @denominator) % 
@denominator
END
 
GO

----------


## rezaei manesh

آقای linux ممنون از کدها تون - اگه می شه یکم راجع به function  ها تون توضیح بدین که هر کدوم چه کار می کنند.
من با روش آقای Linux  بیشتر موافق هستم 
مثلا من در یک جدولم من 6 تاریخ و 6 ساعت دارم اگه بخوام برای مثال join کنم  باید باید چندتا فیلد رو join کنم!  در حالی که برای محاسبه باز باید یک سری اعمال رو انجام بدم  یعنی نمی تونم فقط با یک کویری کار کنم باید رکورد ها رو تک تک محاسبه کنم و عملیاتی رو انجام بدم که فکر کنم استفاده از روش Linuxبهتر باشه حداقل برای موارد مشابه
یک سری هم به این لینک بزنید من اونجا یک سوالی رو مطرح کردم که زیاد  بی ربط با نحوه کار با تاریخ ها نیست (یعنی باید همه حالات ها و اعمالی که قرار صورت بگیره رو بررسی کنیم)
https://barnamenevis.org/showthread.php?t=59036
الان که کد linux رو چک می کردم یک اشتباه خیلی کوچولو پیدا کردم که می گم که اونو تصحیح کنید (البته فکر کنم اشکال تایپی باشه)

CREATE FUNCTION dbo.Persian2Civil(@year int, @month int, @day int)
RETURNS char(10) AS

که بجای 10 باید 20 رو قرار بدید چون خروجی اون از 10 کاراکتر بیشتر هستش

----------


## SabaSabouhi

سلام
من هنوز از Vista یا SQLServer 2005 استفاده نکردم، اما شنیده بودم که تاریخ جلالى (همون هجرى شمسى) رو هم پشتیبانى مى‌کنن. آیا این طور نیست؟

در مورد توابع تبدیل تاریخ هم من دو تابع براى تبدیل شمسى به میلادى و برعکس دارم که فکر مى‌کنم از تمام توابع موجود سریع‌تر و کوتاه‌تر باشه البته محدود هست به smalldatetime.
اگر به دردتون مى‌خوره بفرستم اینجا.

صبا صبوحى

پ.ن: این تابع در تمام دامنه تعریف تست شده و هیچ اشکالى ندارد.

----------


## rezaei manesh

vista رو نمی دونم اما sql2005هنوز کامل پشتیبانی نمی کنه اما فکر کنم قرار توی آینده ای نزدیک این کار رو بکنه اصلا حقیقتش من واسه همین هم نرفتم سراغ 2005 گفتم هر موقع برادری شو ثابت کرد بعد می رم و هم اینکه این پایگاه داده عمومی تر بشه بعد می رم.

اگه توابع تون رو بذارید ممنون می شم

----------


## rmb_ali

دوستان راه استفاده از این فانکشن ها رو میشه در حد مبتدی توضیح بدید البته من یکسری تابع پیدا کردم ببینید چطوره اون فانکشن تو آدرسه زیره:
http://www.sayan.ir/PrintableArticle.aspx?ArticleID=195

----------


## reza6384

سلام. ضمن تشکر بسیار فراوون از دوست عزیزمون H_BAQERY که واقعا Solution اش خوشحالم کرد، عالی بود، نمی دونم چرا تاحالا به فکرم نرسیده بود.

من هم برای ادامه تشکر یه دیتابیس توی SqlServer2000 به اسم PersianDates ساختم و توی جدول ALL_DATE از سال 1998 تا سال 2018 رو ذخیره کردم. یه توضیح هم بدم و اون اینکه با دو حالت Right to left , left to right رشته تاریخ فارسی رو ذخیره کردم. چون مثلا ممکنه تو CrystalReport ها اینوری بشه و توی Datagridview اون وری !

در هر صورت خیلی Solution باحالی بود جناب H_BAQERY ، دمت گرم.

فایل دیتابیس رو هم ضمیمه کردم.

----------


## hamed-p

> میلادی به شمسی
> 
> CREATE FUNCTION [dbo].[MiladiTOShamsi] (@MDate  DateTime)  
> RETURNS Varchar(10)
> AS  
> BEGIN 
>    DECLARE @SYear  as Integer
>    DECLARE @SMonth  as Integer
>    DECLARE @SDay  as Integer
> ...


*سورس dbo.ReversDate* 
و dbo.SubStrCount را نگذاشتید

----------


## Kamyar.Kimiyabeigi

CREATE FUNCTION dbo.ReversDate (@DateStr varchar(10))
RETURNS varchar(10)

AS

BEGIN
  DECLARE @TempStr varchar(10)
  DECLARE @StartIndex int
  DECLARE @SubStrLen int
  DECLARE @i int

  SET @TempStr = ''
  SET @StartIndex = LEN(@DateStr) + 2
  SET @i = LEN(@DateStr)
  WHILE @i > 0
  BEGIN
    IF SUBSTRING(@DateStr,@i,1) IN ('/', '-')
    BEGIN
      SET @SubStrLen = @StartIndex - (@i + 2)
      SET @StartIndex = @i + 1
      SET @TempStr = @TempStr + SUBSTRING(@DateStr,@StartIndex,@SubStrLen) + SUBSTRING(@DateStr,@i,1)
    END
    SET @i = @i - 1
  END
  IF @TempStr <> ''
  BEGIN
    SET @SubStrLen = @StartIndex - 2
    SET @TempStr = @TempStr + SUBSTRING(@DateStr,1,@SubStrLen)
  END
  ELSE
    SET @TempStr = @DateStr
  RETURN @TempStr
END





CREATE  FUNCTION SubStrCount(@SubStr varchar(8000), @MainText Text)  
RETURNS  int 
AS  
BEGIN 
  DECLARE @StrCount int
  DECLARE @StrPos int

  SET @StrCount = 0
  SET @StrPos = 0
  SET @StrPos = CHARINDEX( @SubStr, @MainText, @StrPos)

  WHILE @StrPos > 0
  BEGIN
    SET @StrCount = @StrCount + 1
    SET @StrPos = CHARINDEX( @SubStr, @MainText, @StrPos+1)
  END

  RETURN  @StrCount  
END

----------


## JavanSoft

> سلام. ضمن تشکر بسیار فراوون از دوست عزیزمون H_BAQERY که واقعا Solution اش خوشحالم کرد، عالی بود، نمی دونم چرا تاحالا به فکرم نرسیده بود.
> 
> من هم برای ادامه تشکر یه دیتابیس توی SqlServer2000 به اسم PersianDates ساختم و توی جدول ALL_DATE از سال 1998 تا سال 2018 رو ذخیره کردم. یه توضیح هم بدم و اون اینکه با دو حالت Right to left , left to right رشته تاریخ فارسی رو ذخیره کردم. چون مثلا ممکنه تو CrystalReport ها اینوری بشه و توی Datagridview اون وری !
> 
> در هر صورت خیلی Solution باحالی بود جناب H_BAQERY ، دمت گرم.
> 
> فایل دیتابیس رو هم ضمیمه کردم.


اين روش را قبلا ما استفاده ميكرديم و افت سرعت شديدي داشتيم اما بعد از استفاده از فانكشنها دوست عزيزمان آقاي linux در مقايسه و در مقياس 100000 ركورد متوجه شديم كه زمان اجراي دستور كاهش پيدا كرد (حدود 2.5 برابر بهتر شد )
در عين حال در همان زمان بنده جدول مقايسه ايي از توابع دوست عزيزمان آقاي Linux و جدول خودمان كه در دلفي برنامه آن نوشته شده بود در اورديم كه متوجه 130 اشتباه در جداول خودمان شديم .

----------


## linux

> اين روش را قبلا ما استفاده ميكرديم و افت سرعت شديدي داشتيم اما بعد از استفاده از فانكشنها دوست عزيزمان آقاي linux در مقايسه و در مقياس 100000 ركورد متوجه شديم كه زمان اجراي دستور كاهش پيدا كرد (حدود 2.5 برابر بهتر شد )
> در عين حال در همان زمان بنده جدول مقايسه ايي از توابع دوست عزيزمان آقاي Linux و جدول خودمان كه در دلفي برنامه آن نوشته شده بود در اورديم كه متوجه 130 اشتباه در جداول خودمان شديم .


الان کلا در تبدیل تقویم ها بحث بر سر محاسبه سال کبیسه هست، قانون چون الگوریتم خاصی را معرفی نکرده هرکسی روشی را پیشنهاد می دهد که 2 روش خیلی استفاده می شود که این روشی که در این توابع استفاده شده از روشی که در توابع تبدیل تاریخ در دات نت شده فرق می کنه. به خاطر همین ممکن در سالها 1403 دچار مشکل بشید، کلا هم نمیشه گفت کدام روش درست هست یا نیست، تا موقعی که قانون یکی از این روشهای موجود را مبنا قرار نده همین مشکل هست.

----------


## Arghavan_Reza

با سلام به دوستان،
دو تابع زیر را جهت تبدیل تاریخ میلادی به شمسی و بالعکس نوشته ام. می توانید امتحان کنید:
1 - تبدیل تاریخ میلادی به شمسی:

CREATE FUNCTION DateFarsi(@DateLatin AS DateTime)
RETURNS CHAR(10) AS  
BEGIN 
	DECLARE @DateFarsi CHAR(10)
	
	DECLARE @Days int
	DECLARE @Tmp int
	
	DECLARE @Year_Farsi int
	DECLARE @Month_Farsi int
	DECLARE @Day_Farsi int
	
	SET @Days = DATEDIFF(DAY, '19000320', @DateLatin)

	SET @Year_Farsi =	1279
	SET @Month_Farsi =	01
	SET @Day_Farsi =	01

	SET @Tmp = @Days / 365

	IF (@Tmp * 365) + ((@Tmp + 3) / 4) > @Days
		SET @Tmp = @Tmp - 1
	SET @Year_Farsi = @Year_Farsi + @Tmp
	SET @Days = @Days - (@Tmp * 365) - ((@Tmp + 3) / 4)

	IF @Days <= 186
	BEGIN
		SET @Tmp = @Days / 31
		SET @Month_Farsi = @Month_Farsi + @Tmp
		SET @Days = @Days - (@Tmp * 31)
	END
	ELSE
	BEGIN
		SET @Days = @Days - 186
		SET @Tmp = @Days / 30
		SET @Month_Farsi = @Month_Farsi + @Tmp + 6
		SET @Days = @Days - (@Tmp * 30)
	END
	SET @Day_Farsi = @Day_Farsi + @Days

	RETURN REPLACE(STR(@Year_Farsi, 4, 0) + 
		           STR(@Month_Farsi, 2, 0) + 
		           STR(@Day_Farsi,2, 0), ' ', '0')
END

2 - تبدیل تاریخ شمسی به میلادی:

CREATE FUNCTION DateLatin(@DateFarsi CHAR(10))  
RETURNS DateTime AS
BEGIN 
	SET @DateFarsi = REPLACE(@DateFarsi, '/', '')

	DECLARE @Days BigInt

	DECLARE @Year_Farsi int
	DECLARE @Month_Farsi int
	DECLARE @Day_Farsi int

	SET @Year_Farsi =	CONVERT(int, SUBSTRING(@DateFarsi, 1, 4))
	SET @Month_Farsi =	CONVERT(int, SUBSTRING(@DateFarsi, 5, 2))
	SET @Day_Farsi =	CONVERT(int, SUBSTRING(@DateFarsi, 7, 2))

	SET @Days = ((@Year_Farsi - 1279) * 365) + ((@Year_Farsi - 1276) / 4)

	IF @Month_Farsi <= 7
		SET @Days = @Days + ((@Month_Farsi - 1) * 31)
	ELSE
		SET @Days = @Days + ((@Month_Farsi - 7) * 30) + 186

	RETURN DATEADD(DAY, @Days + @Day_Farsi - 1, '19000320')
END

انشاء الله مقبول بیافتد.

----------


## Arghavan_Reza

ساده است!
بدون اینکه به این فکر کنید که سال کبیسه در سیستم های میلادی و شمسی کی است و چه ارتباطی با هم دارند و شروع سال میلادی در چه تاریخی از سال شمسی اتفاق می افتد یا بالعکس یا مثلا ماه های میلادی هر کدام چند روز است یا ... به این مسئله توجه کنید که تعداد روزهایی که از مبدا (یا مثلا 1/1/1279 شمسی یا 20/3/1900 میلادی ) تا الان (یا هر تاریخ مشخص دیگری) گذشته است در هر دو سیستم یکسان است. (شاید جابجایی سال کبیسه در سال 1375 شمسی به همین دلیل باشد.)
و من الله توفیق ...

----------


## linux

> ساده است!
> بدون اینکه به این فکر کنید که سال کبیسه در سیستم های میلادی و شمسی کی است و چه ارتباطی با هم دارند و شروع سال میلادی در چه تاریخی از سال شمسی اتفاق می افتد یا بالعکس یا مثلا ماه های میلادی هر کدام چند روز است یا ... به این مسئله توجه کنید که تعداد روزهایی که از مبدا (یا مثلا 1/1/1279 شمسی یا 20/3/1900 میلادی ) تا الان (یا هر تاریخ مشخص دیگری) گذشته است در هر دو سیستم یکسان است. (شاید جابجایی سال کبیسه در سال 1375 شمسی به همین دلیل باشد.)
> و من الله توفیق ...


تعداد روزهای گذشته از مبدا برای همه تقویم ها یکسان هست و این پایه تبدیل تقویم ها به یکدیگر هست یعنی در تمام مبدلهای تقویم یک روز را مبدا فرض می کنند مثلا 1/1/1900 روز صفرم هست. حالا تعداد روزهای گذشته از این تقویم را داشته باشید می توانید به تقویم مورد نظر تبدیل کنید.
حالا فرض کن روز 1/1/1900 روز صفرم تقویم ما باشد، حالا من می خواهم شما بفرمایید که روز 42148 ام را چگونه به تقویم شمسی و میلادی تبدیل می کنید؟

----------


## Arghavan_Reza

> حالا فرض کن روز 1/1/1900 روز صفرم تقویم ما باشد، حالا من می خواهم شما بفرمایید که روز 42148 ام را چگونه به تقویم شمسی و میلادی تبدیل می کنید؟


محاسبه تعداد روزهای گذشته (42148) بخشی از وظیفه این توابع است، خیلی سخت نگیرید. می دانم برای آشنایی دیگران سوال کرده اید:


> در مورد این الگوریتم توضیحی میدی؟


 و حتما الگوریتم توابع فوق را خوب فهمیده اید.

----------


## xmatrix

با سلام و تشکر از همه دوستان و بحث هایی که بسیار مفید هستند.
روش های متفاوتی مطرح شدند، در مورد روش sqlpro اضافه کردن یک فیلدchar 10 مهندسی نرم افزار را زیر سوال نبرده و باعث آنرمال شدن جداول نمی گردد.چون اصول نرمال سازی نسبی هستند و تئوریک و در بسیاری از مواقع CostBenefit در دنیای واقعی ما را به استفاده از روش های غیرقانونمند هدایت می کند.و باید هدف از نرمال سازی را بدانیم و در جاهایی که نیاز است رعایت کنیم.

همچنین من یک نکته که خودم رعایت میکنم را به مطالب شما اضافه می کنم.چون بیشترین حالت استفاده از sql معماری کلاینت سرور است بهتر است بجای وارد کردن بار تبدیل تاریخ به sql تبدیل را در سطح UI انجام دهید و این یعنی تقسیم بار محاسبه به کلاینت ها

در ضمن استفاده از جدول تاریخ های فارسی و join آن و ایجاد یک view نیز روش خوبی برای استفاده در سطح sql است.البته معماری برنامه در انتخاب روش تبدیل تاریخ موثر است.

از همه بابت نظراتشان متشکرم.

----------


## Kamyar.Kimiyabeigi

> روش آقای Kamyar.Kimiyabeigi درباره روز آخر سال درست عمل نمی‌كند!


اون Function ايي كه من گذاشتم فقط براي آخرين روز سال كبيسه يعني 30 اسفند درست كار نميكند ولي براي 29 اسفند درست كار ميكنه

----------


## mobin-co

سلام 
من مشکلی که دارم این هست که متاسفانه 360000 تاریخ شمسی دارم که به صورت رشته در جدول ذخیره شده.از طرفی نرم افزاری که من دارم استفاده می کنم فقط تاریخ میلادی رو میشناسه. کل این جریان هم رو وب هست پس باید قبل از upload تاریخ ها رو درست کنم.
و اکر از الگوریتم استفاده کنم زمان load میره بالا ، اگر میتونین لطفاکمکم کنین تا این رشته ها رو به تاریخ میلادی تبدیل کنم در ضمن اگر کسی سورس هم تو سی شارپ داره برام بذاره ممنون می شم. بزرگترین مشکلم هم اینه که سیستم اجازه دستکاری تو داده با فرمت تاریخ رو بهم نمی ده ممنون

----------


## bad_boy_2007

سلام رفقا
امروز بعد از تقریبا 2 سال مجدد تو این تاپیک اومدم ، تقریبا 2 سال پیش با استفاده از کدی که کاربر Linux گزاشته بود تو برنامه هام شروع به کار کردم و کد بسیار سریع و خوب اجرا میشه .
تقریبا میشه گفت هیچ مشکلی باهاش ندارم 
بزرگترین ویو ما که اطلاعات کل سیستم رو نشون میده 32 هزار رکورد داره که با لحاظ کردن Union All حدود 30 جدوم و سورت بر روی فیلد تاریخ و تبدیل تاریخ میلادی به شمسی حدود 2 ثانیه طول میکشه که تمام داده ها رو لود کنه .

و اما منظورم من از ارسال این پست ، نکته ای که به نظرم رسید میتونه مفید باشه اینه که در اکثر موارد داد های من و اکثر کاربران دیگر بصورت ذیل است :

01/01/2001
01/01/2001
01/01/2001
01/01/2001
01/01/2001
01/01/2001
...
02/01/2001
02/01/2001
...
10/10/2001

اگر کمی دقت کنید میتوانیم این تابع را کمی بهینه تر کنیم ، بدین معنی که برای رکورد اول تابع تبدیل تاریخ را انجام بدهد و برای رکوردهای بعدی اگر تاریخ نیاز به محاسبه داشت مجدد این محاسبه انجام شود در غیر این صورت تاریخ محاسبه شده در رکورد قبلی بازیابی شود .

نمیدانم توانستم منظورم را برسانم یا نه ؟

اینگونه فرض کنید برای تاریخ 15/01/2010 این تابع را فراخوانی کرده ایم و این تابع محاسبات را انجام میدهد و در رکورد بعدی هم همین تاریخ (که در رکورد قبلی یک بار تبدیل شده بود) را باید مجدد تبدیل کنیم ، حال اگر بتوانیم مقدار تاریخ قبلی را در متغییری قرار دهیم مشکل رفع میگردد .

یعنی نیاز داریم در تابع 2 مقدار را ذخیره کنیم و بتوانیم در فراخوانی بعدی این مقادیر را بخوانیم ، یعنی یک چیزی تو مایه های متغییر های Static در C


به این شکل تقریبا میشه گفت سرعت تابع بیش از 2 برابر میشود

----------


## linux

> سلام رفقا
> امروز بعد از تقریبا 2 سال مجدد تو این تاپیک اومدم ، تقریبا 2 سال پیش با استفاده از کدی که کاربر Linux گزاشته بود تو برنامه هام شروع به کار کردم و کد بسیار سریع و خوب اجرا میشه .
> تقریبا میشه گفت هیچ مشکلی باهاش ندارم 
> بزرگترین ویو ما که اطلاعات کل سیستم رو نشون میده 32 هزار رکورد داره که با لحاظ کردن Union All حدود 30 جدوم و سورت بر روی فیلد تاریخ و تبدیل تاریخ میلادی به شمسی حدود 2 ثانیه طول میکشه که تمام داده ها رو لود کنه .
> 
> و اما منظورم من از ارسال این پست ، نکته ای که به نظرم رسید میتونه مفید باشه اینه که در اکثر موارد داد های من و اکثر کاربران دیگر بصورت ذیل است :
> 
> 01/01/2001
> 01/01/2001
> ...


البته من این کد را برای sql sererv 2000 نوشته بودم که بعد ها با آمدن sql server 2005 و دات نت 2  با استفاده از کد های دات نت  باز نویسی کردم.
چیزی که شما می خواهید در این تابع قابل انجام نیست. شما می توانید موقع صدا کردن این تابع این کنترل را انجام دهید. البته با دستورات sql هم راحت نیست.

----------


## sia_2007

دوستان خواهش میکنم یک لحظه تامل کنید
بعضی دوستان یک جدول شمسی اظافه داشتند و با JOIN معادل شمسی یک تاریخ میلادی رو به دست میآوردند.
عده ای دیگه که از یک سری FUN استفاده کردند که کندی خود الگوریتم و خود FUN و Cache نشدن آن بسیار مسئله زاست.
بعضی ها اسم از VIEW آوردند که من نفهمیدم VIEW چه جوری قراره تو این سیستم کار کنه ؟
استفاده از Cursor برای افزایش رکوردهای جدول شمسی هم که نوبر بود.
---
دوستان مگر ما برنامه نویس پلتفرم Net. نیستیم ؟
خب ما یک کلاس داریم که در سمت کلاینت که تاریخ میلادی رو به تاریخ جلالی یا همون شمسی تبدیل میکنه.
و اصولا بحث بر سر کلاینت نیست.
خب با CLR Programming یک Type هم در سمت سرور درست کنیم مثلا با نام جلالی که در خودش تاریخ شمسی نگه داری کند.
هم سریع است.
هم اعتبارسنجی اش با خودش است.
هم میتوان یک سری متد به آن اظافه کرد؛ که مثلا نام کامل ماه را برگرداند و ... .
یه بنده خدایی چند صد سال قبل نشسته بدون هیچ امکاناتی مسائلی رو حساب کرده که هنوز که هنوزه اون محاسبات بالاترینه و تقویم ما دقیق ترین تقویم دنیاست.
تن اون بنده خدا رو تو قبر نلرزونیم.
تازه شما خودتون حساب کنید فرضا اگه این تاپیک ترجمه شه و بیفته دست یکسری مثلا هندی چه جوری مضحکه میشیم ؟
در نهایت برای اون سری از دوستانی که فعلا تاریخ میلادی دارند؛ میتونن یک سری کل میلادیهاشون رو بخونند و پس از تبدیل با کد C#‎‎ در فیلد جلالی بنویسند.
و اونهایی که شمسی رو به صورت nchar10 ذخیره کردند؛ در همان کلاسی که تاریخ میلادی رو به شمسی تبدیل میکنه؛ میتونین شمسی رو به صورت سال و ماه و روز جدا بدید و میلادی تحویل بگیرید.
هر چند من خودم با extension method اینها رو به  DateTime  و SHAMSIUDT اظافه کردم.
دیگه به نظر من مشکلی نمی مونه جز اینکه اون تایپ جلالی.
باور کنید من اگر میتوانستم اون رو در اختیارتون میذاشتم. ولی چنین اختیاری ندارم.
اما کد C#‎‎ اون رو در اختیارتون میذارم هر چند که با اطلاعاتی که در بعضی از دوستان میبینم میدونم کامل تر از این رو میتونند طراحی کنند؛ به چند دلیل :
در طراحی Validation جدی گرفته نشده چون من از کمپوننت DateTime Picker استفاده میکنم هم برای شمسی، هم برای جلالی و اونها به خوبی مسائل کبیسه و خبیسه و ... رو در نظر گرفتن.
از extension method استنفاده بیهوده نکنید ؛ حتی این استفاده من هم بی جا بوده است.
در ضمن فکر میکنم حداقل صحیح ترین راه حل مسئله رو گفتم
دوستان اگر نظری دارند و اشکالی در راه حل من میبینند بگویند.
موفق باشید

----------


## mnodehi

با سلام آقای linux.
من کدی که  گذاشته اید را امتحان کردم. در تبدیل تاریخ میلادی به شمسی یک روز جلوتر را نمایش می دهد. فکر می کنید چرا اینطور است. آیا اگر عددی که در تابع Civil2Persian گذاشته اید بجای 2415021 عددد 2415020 بگذاریم مشکل حل می شود؟

----------


## JavanSoft

> با سلام آقای linux.
> من کدی که  گذاشته اید را امتحان کردم. در تبدیل تاریخ میلادی به شمسی یک روز جلوتر را نمایش می دهد. فکر می کنید چرا اینطور است. آیا اگر عددی که در تابع Civil2Persian گذاشته اید بجای 2415021 عددد 2415020 بگذاریم مشکل حل می شود؟


من هم كد را از آقاي linux گرفتم و بدون مشكل در حال كار است

----------


## hamed.rezaei

سلام 
برای تاریخ شمسی میشه دستورات vb رو وارد sql کرد .می دونین که vb 2008 به  بالا تقیم شمسی و داخلش داره و راحت تاریخ میلادی و تبدیل میکنه حتی ماههای 30 و31 روزه هم در نظر میگیره

----------


## panahande

با سلام
من اين دو تا تابع را نوشتم 
براتون ميگذارم تا شما و بقيه هم استفاده كنيد
فايلها txt هستند ميتوانيد كد موجود را در SQL كپي و اجرا كنيد.

----------


## shadmani

سلام و صد سلام به دست اندرکاران و کلیه کاربران

در تبدیل تاریخ شمسی به میلادی و بلعکس با مطالعه کمی که در این سایت نمودم تنها تجربه خویش را بازگو می کنم:
بعضی زمانها می بایست در سطح تنها sql این تبدیل صورت گیرد و برخی موارد در خود برنامه موردی ندارد، بطور مثال اگر Procedure در sql نوشته شده باشد و بخاطر عملیات ریاضی که در آن صورت پذیرفته یا به هر دلیلی که باعث تکرار رکوردها و ایجاد اشکال در جواب می نماید تنها می توان تاریخ را در قسمت مثلا where آورد پس کلیه عملیات در سطح sql است گرچه با آمدن linq تا حد زیادی این مشکل برطرف شده اما نه کاملا شایدم من مسلط نیستم ضمنا function های موجود در این سایت نیز صحیح عمل می کنند، لذا با توجه به شرایط راه حل انتخاب می گردد. خود من هم در net. هم در sql این تبدیل را با در نظر گرفتن شرایط موجود انجام می دهم. ضمنا کاربر محترم Kamyar.Kimiyabeigi بسیار ممنون. با تشکر شادمانی

----------

