• وبلاگ : شايد سخن حق
  • يادداشت : تبديل ساده تاريخ ميلادي به شمسي در SQL Server
  • نظرات : 1 خصوصي ، 28 عمومي
  • تسبیح دیجیتال

    نام:
    ايميل:
    سايت:
       
    متن پيام :
    حداکثر 2000 حرف
    كد امنيتي:
      
      
     <      1   2      
     
    + احمدي 
    مشکل کوتيشن و تک کوتيشن نيست
    پاسخ

    من همين الآن كل كد موجود در لينك داده شده را كپي كردم در نوت‌پد، كوتيشن‌ها را با آپستروف جايگزين كردم، بردم داخل اديتور SQL Server 2008 اجرا كردم. تابع SDAT ساخته شد. با كد ( SELECT [dbo].[SDAT] ("2016/04/09" , "") ) تست كردم، پاسخ داد ( شنبه 21 فروردين 1395 ) كه درست بود. شايد نسخه SQL شما متفاوت است يا دليل ديگري. موفق باشيد.
    + احمدي 

    سلام مجدد

    کدي که در لينک معرفي شده ، در سيستم من خطا ميگيره!

    آيا لازمه که کد ايشون اصلاح بشه؟ يا همين کد، کد نهايي هست؟

    که در اينصورت روي تعاريف متغير ها داراي اشکال هست

    پاسخ

    سلام. احتمال مي‌رود فراموش فرموده باشيد كه كوتيشن‌مارك‌هاي داخل اين كد را با نشان آپستروف جايگزين فرماييد. كوتيشن‌ها دوتايي هستند، ولي آپستروف تكي‌ست. اگر اين جايگزيني انجام نشود، كد خطا مي‌دهد. يك بررسي بفرماييد.
    + احمدي 

    سلام

    اين کد را سال گذشته استفاده ميکردم درست کار ميکرد و لي امثال تاريخ ميلادي را که به شمسي تغيير ميده تاريخ دو روز پيش را نشون ميدهو لطفا يه نگاه بهش بندازيد

    پاسخ

    سلام. صحيح مي‌فرماييد. اين به دليل محاسبه «كبيسه‌»هاست. سال‌هاي ميلادي كبيسه‌هاي خاص خود را دارند و سال‌هاي شمسي نيز. غير از اين‌كه هر چهار سال يك‌بار ما كبيسه داريم، در يك بازه زماني كبيسه‌هاي پنج‌ساله اتفاق مي‌افتند. كد فوق را چند ماه پيش اصلاح كردم كه مشكل كبيسه آن حل شده است. يك كد جديد هم يك بزرگواري نوشته‌اند كه خيلي سريع‌تر از كد فوق است. نشاني آن را در پي‌نوشت هفتم مي‌يابيد. مي‌توانيد از آن استفاده كنيد كه قطعاً بسيار بهتر است. موفق باشيد.
    کد در آدرس زير است جهت تست و استفاده ساير علاقمندان
    اينجا
    پاسخ

    تشكر.
    + MAMEHDI 
    با سلام و خسته نباشيد خدمت شما کدي را که گذاشتيد بعلت اينکه روز به روز اضافه ميکند داراي حلقه طولاني است و روز هفته چه عددي و چه حرفي را اشتباه چاپ ميکند مثلا امروز که يکشنبه 17 آبان 94 و دومين روز هفته است را ميگويد شنبه و اولين روز من داخل کد شما دست بردم و بسيار سريعتر شد و چون تقريبا 90% کد عوض شد هم اسم متغييرها را عوض کردم و هم تعداد آنها را کاهش دادم اگر خواستيد کدش را ميگزارم تا يک تست هم از لحاظ درستي و هم از لحاظ سرعت در رکوردهاي بالا با کد قبلي تست شود تا شايد نياز به جدول ديگر نباشد با تشکر
    پاسخ

    سلام. متغيّر DayCnt را تغيير دادم و مشكل روز يكشنبه حل شد. اما نسبت به الگوريتم آن، بله صحيح مي‌فرماييد. الگوريتم خيلي كندي دارد، ولي قابل فهم‌تر نسبت به ساير الگوريتم‌ها. اگر لطف بفرماييد و كد را ايميل كنيد، آن را در همين پست وبلاگ معرفي خواهم كرد. من كدهاي مختلفي را ديده‌ام تا به حال. ولي علّت اين‌كه اين كد را انتخاب كردم، سادگي بي‌حدّ آن بود كه مي‌‌شود دقيقاً از اتفاقاتي كه در لوپ و حلقه مي‌افتد اطمينان حاصل كرد. البته كد فوق مربوط به بنده نيست و من نيز آن را از كامنت‌هاي وبلاگي ديگر برداشته و در آن دست برده‌ام كه نشاني‌اش در پست ذكر شده است. تشكر.
    + بازم علي 
    سلام.بايد بگم مشکل قبلي بنده حل شد اما يه ايراد و اون اينکه توي تابع دوم(G2J_Fast)نميتونيد فرمت خروجي را تعيين کنيم!
    پاسخ

    سلام. آيا جاي كوتيشن‌مارك‌ها را با آپستروف عوض كرديد؟ من به جهت اين‌كه در وبلاگ نمي‌شد از آپستروف استفاده كرد، كوتيشن‌مارك قرار دادم. تابع به نحوي طراحي شده كه حتي اگر رشته اشتباهي هم در فرمت قرار دهيد، متوقف نشده و كارش را انجام مي‌دهد. يعني تنها كاري كه با رشته فرمت انجام مي‌پذيرد اين است كه پس از توليد تاريخ شمسي، با نمادهاي استفاده شده در رشته فرمت جايگزين مي‌گردد. پس منطقي نيست و نبايد درج فرمت مشكلي در اجراي تابع اصلي ايجاد نمايد. يك اشتباهي هم ممكن است صورت داده باشد و آن اين‌:كه: من دو عدد تابع G2J‌ نوشته‌ام؛ اولي بدون فرمت است و اصلاً چنين پارامتري ندارد و دومي دارد. شما ممكن است تابع اول را ساخته باشيد و معلوم است كه حالا نمي‌توانيد پارامتري به عنوان فرمت براي آن ارسال كنيد. تابع را باز كنيد و ببينيد كدام را ساخته‌ايد. اگر در سطر اول آن پارامتر فرمت ثبت نشده، آن تابع را حذف كنيد؛ DROP و يك بار ديگر تابع دوم G2J كه داراي دو پارامتر و آرگومان است @intDate DATETIME, @Format NVARCHAR را بسازيد.
    + علي 
    سلام
    اولا که خدا خير بهتون بده.
    من يه سري مشکل دارم راهنمايي بفرماييد ممنون ميشم:
    آخرين کد مربوط به ايجاد پروسيجر (که داخلش يه جدول ايجاد ميکنه)پروسيجر ايجاد شده ولي جدول Miladi_Shamsi نه.چون وقتي تابع بعدي رو ميخوام اجرا کنم جدوله رو نميشناسه.چرا؟؟
    و اينکه تابع اولي ايجاد شده ولي وقتي برا استفاده چند کاراکتر اسمشو ميزنم نمياردش کامل هم که بنويسم جواب ميده ولي زير اسمش خط قرمز موج دار گذاشته چرا؟
    ممنون
    پاسخ

    الحمدلله كه اين مشكل حل شد. گاهي كمي با تأخير شناسايي توابع و جداول صورت مي‌پذيرد. من خودم معمولاً معطل نمي‌شوم تا نام جداول و توابع را خود ابزار مديريت ديتابيس كامل كند، اسم‌ها را كامل مي‌نويسم و اجرا مي‌كنم.
    با سلام در خروجي نمايش زمان هم نياز دارم لطفا کمک کنيد تشکر
    پاسخ

    زمان در SQL نياز به تبديل ندارد، مگر اين‌كه بخواهيد آن را به وقت تهران 3:30+ نمايش دهيد كه تبديل بخواهد. كافيست در آخرين خط كه خروجي ساخته مي‌شود (متغيّر DayDate@) ساعت و دقيقه را اضافه كنيد. تابع ()GETDATE تاريخ و زمان فعلي را مي‌دهد، حالا با تابع CONVERT و استفاده از كد 108 تنها ساعت و دقيقه و ثانيه را مي‌گيريد. شرح كامل آن و كدهاي مورد استفاده را در نشاني http://www.w3schools.com/sql/func_convert.asp مشاهده بفرماييد. به اين صورت: (CONVERT(VARCHAR(8), getdate(), 108
    + احمدي 
    الگوريتم کامل بود ، ممنون
    پاسخ

    موفق باشيد.
    + احمدي 
    در توضيح سوالم بايد بگم: اگه من تاريخ مبدا را 1/1/1394 در نظر بگيرم وقتي يکي يکي به اين تاريخ اضافه بکنم ،بخوام 1/2/1394 را ثبت کنم چکار بايد بکنم؟
    پاسخ

    روش‌هاي متنوعي براي اين كار وجود دارد. اولاً مي‌توانيد اين كار را در لايه برنامه‌نويسي با زباني كه كار مي‌كنيد، Net. يا php مثلاً انجام دهيد كه در آن صورت بايد يك مجموعه INSERT‌ بسازيد و به يك‌باره يا بخش‌بخش اجرا بفرماييد. يا اين‌كه برويد در لايه SQL و يك تابع به زبان T-SQL بنويسيد؛ مبدأ و مقصد را بگيرد و در يك لوپ انداخته، تمام ركوردها را مستقيم بسازد. از سوي ديگر نحوه ذخيره داده تاريخ هم متنوع است. ممكن است بخواهيد يك فيلد (CHAR(10 بسازيد و تاريخ شمسي را در قالب يك رشته ذخيره كنيد، يا ممكن است برويد سراغ smalldatetime و به صورت ميلادي تاريخ را ذخيره كرده و سپس هر بار موقع SELECT‌ كردن آن را دوباره به شمسي باز گردانيد. روشي هم وجود دارد كه با استفاده از كدهاي آماده‌اي كه در اينترنت يافت مي‌شود يك فيلد از نوع تاريخ شمسي در ديتابيس ايجاد كنيد. هر كدام از اين‌ها تكنيك خاص خود را دارد. موارد فوق را بررسي نموده، روش مناسب براي كار خود را بيابيد. موفق باشيد.
    + احمدي 

    خيلي خيلي ممنون

    فقط يه سوال:

    من ميخوام يک تاريخ مبدا و يک تاريخ نهايي از کاربر بگيرم و به ازاي هر روز بين اين دوتا تاريخ يک رکورد ثبت کنم چطور ميتونم اين کارو انجام بدم؟

    پاسخ

    به اين ترتيب: 1. تاريخ را به اجزاي تشكيل‌دهنده خود تقسيم كنيد؛ روز، ماه، سال، به عدد كانورت كرده و در سه متغير عددي قرار دهيد. 2. حالا يك حلقه بسازيد كه تكرار شود. 3. در هر تكرار يك واحد به متغير روز اضافه نمايد. 4. كنترل كند ماه بين 0 تا 7 است (31 روزه) يا بين 6 تا 12 (30 روزه) يا 12. 5. اگر ماه 12 است آيا سال كبيسه است (از يك سال كبيسه‌اي به عنوان مبدأ منها شده و بر 4 تقسيم گردد و اگر باقي‌مانده صفر شد كبيسه است). 6. اگر روز از مقدار ممكن در ماه بيشتر شد، يكي به ماه اضافه شده و روز يك شود. 7. مقدار ماه اگر از 12 بيشتر شده يكي به سال اضافه شده و ماه يك شود. 8. اكنون تاريخ فعلي به دست آمده و بايد يك INSERT ساخته شده و ركورد ايجاد گردد. 9. با تاريخ مقصد مقايسه شود و اگر به مقصد رسيده است از لوپ خارج گردد. 10. كار تمام است، مي‌تواند يك پيغام مناسب بازگرداند. اين الگوريتم به نظرم كامل و روشن باشد. موفق باشيد.
    + امير 
    سلام برادر عزيزم من كد شما رو نگاه كردم بسيار عالي بود و جاي تشكر فراوان داره من يك متغيير ديگه هم بهش اضافه كردم جهت تعيين خروجي يعني در زمان فراخواني تابع تعيين ميكنيد كه كدام نوع از خروجي هاي تابع براي شما برگردانده شود
    بجاي اينكه تابع را ويرايش كنيد
    ALTER FUNCTION [dbo].[G2J] ( @intDate DATETIME ,@OutPut_Mod as tinyint)
    -----------------------------------------------------------------------------
    IF @OutPut_Mod = 0
    SET @DayDate = @shRooz + " " + LTRIM(STR(@shDay,2)) + " " + @shMaah + " " + STR(@shYear,4)
    --پنجشنبه 17 ارديبهشت 1394

    IF @OutPut_Mod = 1
    SET @DayDate = LTRIM(STR(@shDay,2)) + " " + @shMaah + " " + STR(@shYear,4)
    --17 ارديبهشت 1394

    IF @OutPut_Mod = 2
    SET @DayDate = STR(@shYear,4) + "/"+LTRIM(STR(@shMonth,2)) + "/" + LTRIM(STR(@shDay,2))
    --1394/2/17

    IF @OutPut_Mod = 3
    SET @DayDate = REPLACE(RIGHT(STR(@shYear, 4), 4), " ", "0") + "/"+ REPLACE(STR(@shMonth, 2), " ", "0") + "/" + REPLACE(( STR(@shDay,2) ), " ", "0")
    --1394/02/17
    پاسخ

    سلام. بله بسيار عالي‌ست. تشكر.
    + amir 
    اين کد اشتباه جواب نميده اشتباه چاپ مي کنه
    پاسخ

    اگر منظور شما از «اشتباه چاپ كردن» اين است كه ترتيب قرارگيري روز و ماه و سال منظم نيست و در هنگام چاپ جابه‌جا قرار مي‌گيرد، اين كاملاً بستگي دارد به نرم‌افزار يا مرورگر مورد استفاده و كدهاي HTML به كاررفته؛ RTL بودن يا LTR‌ بودن. شما براي متناسب‌سازي خروجي تابع فوق با نياز خود كافيست آخرين بخش تابع را تغيير دهيد. وقتي مقدار به خروجي داده مي‌شود، بنده چند نوع تركيب را امتحان كرده و به صورت كامنت‌شده (غيرفعال) قرار داده‌ام. شما سه مقدار سال و ماه و روز را مي‌توانيد به هر ترتيبي كه مايل بوديد يا هستيد به خروجي ارسال بفرماييد. موفق باشيد.
     <      1   2