آموزش تبدیل تاریخ میلادی به شمسی با کدنویسی

نمونه سورس کد پیش رو در وبسایت مرکز درس برای آگاهی شما از تاریخ جلالی پست شده تا دید کلی نسبت به این قضیه پیدا کنید. الگوریتم مورد نظر برای زبان برنامه نویسی swift نوشته شده که برروی شبیه ساز ios و mac تست شده است. لازم به ذکر است از ابزار های swift 2.1.1 و نیز xcode7.2 استفاده شده است . اولین انتشار در تاریخ 1395 می باشد .

الگوریتم تبدیل تاریخ میلادی به تاریخ شمسی

  1. برای نوشتن الگوریتم به اختلاف روز های میان اولین روز سال میلادی ( 1 ژانویه ) و اولین روز سال شمسی ( 20 مارس ) نیاز داریم که برابر با “79” می باشد . 
  2. در این مرحله باید تشخیص دهیم که سال میلادی کبیسه است یا خیر . برای اینکار باید سال میلادی داده شده را بر 4 تقسیم کنیم ، اگر بخشپذیر بود ( باقیمانده برابر صفر ) سال کبیسه است در غیر اینصورت سال میلادی کبیسه نیست . 
  3. با توجه به کبیسه بودن یا کبیسه نبودن سال مشخص می کنیم که در کدامین روز سال میلادی قرار داریم ، که در اینصورت با دو حالت روبرو خواهیم شد : 

 1-3- سال کبیسه باشد

1-1-3- روزی که در آن قرار داریم از 79 بیشتر باشد

به این معنی است که در ماههای بعد از فروردین قرار داریم . حال باید مشخص کنیم که در 6 ماه اول سال شمسی قرار داریم یا در 6 ماه دوم سال قرار داریم . برای اینکار ابتدا ” 79 ” روز از تعداد روز ها کم می کنیم تا در اول فروردین ماه قرار بگیریم . اگر تعداد روز های بدست آمده از  ” 186  ” ( 31 * 6 ) کمتر باشد یعنی در 6 ماه اول سال شمسی قرار داریم ، در غیر اینصورت در 6 ماه دوم قرار داریم .                              

1-1-1-3- اگر در 6 ماه اول سال قرار گرفته باشیم ( dates

تعداد روزها را بر ” 31 ” تقسیم می کنیم ( چرا بر 31 تقسیم کنیم ؟ به این دلیل که در 6 ماه اول سال شمسی قرار داریم . ) ، اگر باقیمانده این تقسیم صفر شد ، خارج قسمت تقسیم برابر با ماه شمسی می شود و روز شمسی برابر با 31 می شود . در غیر اینصورت اگر باقیمانده صفر نشود ماه شمسی برابر با خارج قسمت به اضافه ی یک می شود و روز شمسی همان باقیمانده است .                                                                                        

2-1-1-3- اگر در 6 ماه دوم سال قرار گرفته باشیم

” 186 ” روز از تعداد روز ها کم می کنیم و آن را بر ” 30 ” تقسیم می کنیم ( چرا بر 30 تقسیم می کنیم ؟ چون در 6 ماه دوم سال قرار گرفته ایم  و ماه ها 30 روزه می باشند . ) . اگر باقیمانده این تقسیم صفر شد ، خارج قسمت تقسیم به اضافه ” 6 ” و برابر ماه شمسی قرار خواهد گرفت و روز شمسی برابر  با  30 می شود . اگر باقیمانده صفر نشود ماه شمسی برابر با خارج قسمت به اضافه ” 7 ” می شود و روز شمسی همان باقیمانده است و در نهایت سال شمسی از تفاضل سال میلادی با ” 621 ”  بدست می آید .چرا برای بدست آوردن سال شمسی ، سال میلادی را از   621  کم کردیم ؟  همان طور که در بالا ( 3-1-1 ) ذکر کردیم ، یعنی روز مورد نظر بین اول فروردین تا 11 دی می باشد . 

2-1-3- روزی که در آن قرار داریم کمتر از ” 79 ” است                

به این معنی است که در روزهای بین اولین روز سال میلادی تا اولین روز سال شمسی ( دی ، بهمن ، اسفند ) قرار داریم . اختلاف روز بین اولین روز سال میلادی داده شده و اولین روز دی ماه در سال شمسی را در نظر می گیریم که این اختلاف برای سال کبیسه  ” 11 ” و برای سال غیر کبیسه  ” 10 ” می باشد .        

  • تــوجــه : در این الگوریتم برای مشخص کردن این اختلاف باید سال قبل از سال داده شده را در نظر بگیریم ، به این دلیل که سال قبل بر روی اولین روز سال میلادی تاثیر می گزارد .                    

در نهایت اختلاف تاریخ بدست آمده را با تعداد روز ها جمع می کنیم و آن را بر ” 30 ”  تقسیم می کنیم ( 3 ماه آخر سال شمسی 30 روزه است . ) ، اگر باقیمانده این تقسیم صفر شود ، خارج قسمت تقسیم به اضافه ی ” 9 ” برابر  با ماه برابر با خارج قسمت به اضافه ” 10 ” می شود و روز شمسی همان باقیمانده است . در این حالت سال شمسی از تفاضل سال میلادی با ” 622 ” بدست می آید . ( چون بین 11 دی تا آخر اسفند قرار داریم . )     

 2-3- سال کبیسه نباشد

 دقیقا به مانند الگوریتم سال کبیسه عمل می کنیم ، البته با کمی تفاوت که با مطالعه ی SourcCode متوجه آن خواهید شد . 

راهنما

1- بهتر است برای هر دو سال های میلادی کبیسه و غیر کبیسه یک آرایه ی جداگانه در نظر گرفته شود  .

2- برای مقدار دهی به آرایه های سال کبیسه و غیر کبیسه ، در این الگوریتم باید با توجه به جدول زیر  عمل کنیم : 

آموزش تبدیل تاریخ میلادی به شمسی با کدنویسی

به طور مثال ) می خواهیم آرایه ای از سال غیر کبیسه ( not_leap_year ) را با توجه به جدول بالا مقدار دهی کنیم :

مقدار دهی آرایه به این شکل است که :  عنصر قبل  + عنصر بعد  ،  با این شرط که اولین عنصر از آرایه مقدار صفر (0) را دارد .

not_leap_year = [ 0 , January + 0 , ( January + 0 ) + 28 , .... ]
 not_leap_year = [ 0 , 0 + 31 , 31 + 28 , 59 + 31 , 90 + 30 , 120 + 31 , 151 + 30 , 181 + 31 , 212 + 31 , 
                   243 + 30 , 273 + 31 , 304 + 30 ]
  • نـکتـه 1 : برای not_leap_year ( سال غیر کبیسه ای ) عدد 28 را در نظر می گیریم . برای is_leap_year (سال کبیسه ای ) عدد 29 را در نظر می گیریم . 
  • نـکتـه 2 : باید دقت داشته باشید که طول آرایه از عدد 12 تجاوز نکند ، چون هر سال 12 ماه دارد . 

سورس کد

تابع calcSolarCalendar به صورت یک method تعریف شده و عینا مانند الگوریتم بالا می باشد  . از ویژگی های این الگوریتم : 

  • بدست آوردن تاریخ شمسی از میلادی 
  • بدست آوردن ماه شمسی 
  • بدست آودن روز شمسی 

نــکــته : دوستان دقت داشته باشید برای تست این الگوریتم فقط از سایت Time.ir استفاده کنید . بقیه سایت ها رو که تست کردم الگوریتم درستی نداشتند.

/** in Swift2.1.1 and XCode7.2 **/

import UNIKit
import Foundation



class ViewController: UIViewController {
    
    

    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
	//call the solarcalendar method
        CalcSolarCalendar()
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

   // calcSolarDate method 
   internal func CalcSolarCalendar(){
        
        var difference_between_days:Int = 

        var strMonth = ""
        
        var date:Int = 
        var month:Int = 
        var year:Int = 
        
	//get day , month and year from your divice
        let date_miladi = NSDate()
        let calendar = NSCalendar.currentCalendar()
        let components = calendar.components([.Day , .Month , .Year], fromDate : date_miladi)
        
        let year_miladi = components.year
        let month_miladi = components.month
        let day_miladi = components.day


        //date convert to string and send to the getDayOfWeek method
        let dateFormater = NSDateFormatter()
        dateFormater.dateFormat = "yyy-MM-dd"
        let dateString = dateFormater.stringFromDate(date_miladi)
        
        //day of month
        let not_leap_year = [ , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334]
        let is_leap_year = [ , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335]
        
        if ((year_miladi % 4 ) != ) {
            date = not_leap_year[month_miladi - 1 ] + day_miladi
            
            if(date > 79){
                date = date - 79
                if(date  186){
                    switch (date % 31){
                    case :
                        month = date / 31
                        date = 31
                        break ;
                    default:
                        month = (date / 31) + 1
                        date = (date % 31)
                        break ;
                    }
                    year = year_miladi - 621 ;
                }else{
                    date = date - 186;
                    
                    switch(date % 30){
                    case  :
                        month = (date / 30 ) + 6
                        date = 30
                        break;
                    default:
                        month = (date / 30 ) + 7
                        date = (date % 30)
                        break;
                    }
                    year = year_miladi - 621
                }
            }else{
                if((year_miladi > 1996) && (year_miladi % 4) == 1 ){
                    difference_between_days = 11
                }else{
                    difference_between_days = 10
                }
                date = date + difference_between_days
                
                switch(date % 30){
                case  :
                    month = (date / 30) + 9
                    date = 30
                    break;
                default:
                    month = (date / 30) + 10
                    date = (date % 30)
                    break;
                }
                year = year_miladi - 622;
            }
        }else{
            date = is_leap_year[month_miladi - 1] + day_miladi
            
            if(year_miladi >= 1996){
                difference_between_days = 79
            }else{
                difference_between_days = 80
            }
            if(date > difference_between_days){
                date = date - difference_between_days
                
                if(date  186){
                    switch (date % 31) {
                    case  :
                        month = (date / 31)
                        date = 31
                        break;
                    default:
                        month = (date / 31) + 1
                        date = (date % 31)
                        break;
                    }
                    year = year_miladi - 621
                }else{
                    date = date - 186
                    
                    switch( date % 30){
                    case  :
                        month = (date / 30 ) + 6
                        date = 30
                        break;
                    default:
                        month = (date / 30 ) + 7
                        date = (date % 30 )
                        break;
                    }
                    year = year_miladi - 621
                }
            }else{
                date = date + 10
                
                switch (date % 30){
                case  :
                    month = (date / 30 ) + 9
                    date = 30
                    break;
                default:
                    month = (date / 30 ) + 10
                    date = (date % 30)
                    break;
                }
                year = year_miladi - 622;
            }
        }
        
        switch(month){
        case 1:
            strMonth = "فرودین"
            break;
        case 2:
            strMonth = "اردیبهشت"
            break;
        case 3:
            strMonth = "خرداد"
            break;
        case 4:
            strMonth = "تیر"
            break;
        case 5:
            strMonth = "مرداد"
            break;
        case 6:
            strMonth = "شهریور"
            break;
        case 7:
            strMonth = "مهر"
            break;
        case 8:
            strMonth = "آبان"
            break;
        case 9:
            strMonth = "آذر"
            break;
        case 10:
            strMonth = "دی"
            break;
        case 11:
            strMonth = "بهمن"
            break;
        case 12:
            strMonth = "اسفند"
            break;
        default:
            break;
        }
        
        let dateFormatter = NSDateFormatter()
        dateFormatter.locale = NSLocale(localeIdentifier: "en_US")
        

	//casting int to string
        let int_year_solar:Int = year
        let String_year = String(int_year_solar)
        
	//Converting to Solar date extention (YYY/MM/DD) 
        let format_month = String(format:"%02d" , month)
        let format_date = String(format: "%02d" , date)
        
        
        print("date Solar is : " + String_year + "/" +  format_month + "/" + format_date)
        print("Month is : " + strMonth)


        // date string sened to DayOfWeek Method
        getDayOfWeek(dateString)       
    }

    // getDayOfWeek method
    func getDayOfWeek (today:String) {
        
        
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyy-MM-dd"
        if let todayDate = formatter.dateFromString(today){
            let myCalendar = NSCalendar(calendarIdentifier: "gregorian")
            let myComponents = myCalendar?.components(.Weekday, fromDate: todayDate)
            let weekDay = myComponents?.weekday
            
            let weekDay_solar = ["شنبه" , "یکشنبه" , "‍ دو شنبه" , "سه شنبه" , "چهارشنبه" , "پنج شنبه" , "جمعه"]
            
            if(weekDay != 7){
                for var i= ; i  weekDay_solar.count ; i++ {
                    if(weekDay == i){
                        print("day is : " + weekDay_solar[i])
                    }
                }
            }else{
                print("day is : " + weekDay_solar[])
            }
        }
    }

    
}

        /*
        output is : 
                     date solar is : 1395/07/02
                     month is : مهر
                     day is : جمعه
        */

اگر قصد دارید مقادیر تاریخ میلادی را دستی وارد کنید و یا کاربر خودش دستی وارد کند می توانید به روش زیر و با توجه به کد بالا مقادیر را وارد کنید :

let year_miladi = 2016
let month_miladi = 9
let day_miladi = 23

        /*
        output is : 
                     date solar is : 1395/07/02
                     month is : مهر
                     day is : جمعه
        */

من در سورس کد بالا علاوه بر تبدیل تاریخ و بدست آوردن ماه شمسی  ، متدی برای بدست آوردن روز های هفته با استفاده از Swift نوشتم و برای اینکه درک source code بالا برای شما مشکل نباشه آن ( func getDayOfWeek ) را به صورت جداگانه در این تاپیک قرار می دهم . 

/** Tested in the Swift2.1.1 and XCode7.2 **/
import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        
        // get day , month and year form your device 
        let date_miladi = NSDate()
        let calendar = NSCalendar.currentCalendar()
        let components = calendar.components([.Day , .Month , .Year], fromDate : date_miladi)
        
        
        //date convert to string
        let dateFormater = NSDateFormatter()
        dateFormater.dateFormat = "yyy-MM-dd"
        let dateString = dateFormater.stringFromDate(date_miladi)
        
        // call the method
        getDayOfWeek(dateString)
        
        
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    
    // getDayOfWeek method
    func getDayOfWeek (today:String) {
        
        
        let formatter = NSDateFormatter()
        formatter.dateFormat = "yyy-MM-dd"
        if let todayDate = formatter.dateFromString(today){
            let myCalendar = NSCalendar(calendarIdentifier: "gregorian")
            let myComponents = myCalendar?.components(.Weekday, fromDate: todayDate)
            let weekDay = myComponents?.weekday
            
            let weekDay_solar = ["شنبه" , "یکشنبه" , "‍ دو شنبه" , "سه شنبه" , "چهارشنبه" , "پنج شنبه" , "جمعه"]
            
            if(weekDay != 7){
                for var i= ; i  weekDay_solar.count ; i++ {
                    if(weekDay == i){
                        print("day is : " + weekDay_solar[i])
                    }
                }
            }else{
                print("day is : " + weekDay_solar[])
            }
        }
    }
}

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

سوال ) می خوام ورودی را با استفاده از EditText و از کاربر دریافت کنم ولی روز مورد نظر را به درستی برای من نمایش نمی دهد باید چیکار کنم ؟ 

جواب : کاملا حق با شماست به این دلیل که من فقط و فقط تاریخ سیستم را به متد getDayOfWeek ای که نوشتم ارسال می کنم و نه تاریخ ورودی کاربر . بنابراین برای زمانی که بخواهیم ورودی را از کاربر دریافت کنیم باید به شیوه ی زیر الگوریتم را تغییر دهیم :

//getting input from the user
let year_miladi = 1932
let month_miladi = 9
let day_miladi = 23

//Casting int variable to String
let stryear= String(year_miladi)
let strmonth = String(month_miladi)
let strday = String(day_miladi)

//format (yyy-MM-dd)
let totaldate = stryear + "-" + strmonth + "-" + strday 

// send totaldate to getDayOfWeek Method
getDayOfWeek(totaldate)


   /*
      output is : 
             date solar is : 1395/07/01
             Month is : مهر
             day is : جمعه
   */

منبع : TOSINSO

بیشتر بخوانید :   واحدهای توزین طلا
ساسان سروشه

نوشته‌های مرتبط

دیدگاه‌ها

*
*