الگوریتم تاریخ جلالی ( آموزش )
الگوریتم تبدیل تاریخ میلادی به تاریخ شمسی :
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 <= 186 ) :
تعداد روزها را بر " 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- برای مقدار دهی به آرایه های سال کبیسه و غیر کبیسه ، در این الگوریتم باید با توجه به جدول زیر عمل کنیم :
Length in days | Name | No. |
31 | January | 1 |
28 or 29 leap year | February | 2 |
31 | March | 3 |
30 | April | 4 |
31 | May | 5 |
30 | June | 6 |
31 | July | 7 |
31 | August | 8 |
30 | September | 9 |
31 | October | 10 |
30 | November | 11 |
31 | December | 12 |
به طور مثال ) می خواهیم آرایه ای از سال غیر کبیسه ( 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 = 0
var strMonth = "" var date:Int = 0 var month:Int = 0 var year:Int = 0 //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 = [0 , 31 , 59 , 90 , 120 , 151 , 181 , 212 , 243 , 273 , 304 , 334] let is_leap_year = [0 , 31 , 60 , 91 , 121 , 152 , 182 , 213 , 244 , 274 , 305 , 335] if ((year_miladi % 4 ) != 0) { date = not_leap_year[month_miladi - 1 ] + day_miladi if(date > 79){ date = date - 79 if(date <= 186){ switch (date % 31){ case 0: 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 0 : 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 0 : 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 0 : 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 0 : 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 0 : 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=0 ; i <= weekDay_solar.count ; i++ { if(weekDay == i){ print("day is : " + weekDay_solar[i]) } } }else{ print("day is : " + weekDay_solar[0]) } } } }
/*
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 .
من در سورس کد بالا علاوه بر تبدیل تاریخ و بدست آوردن ماه شمسی ، متدی برای بدست آوردن روز های هفته با استفاده از 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=0 ; i <= weekDay_solar.count ; i++ { if(weekDay == i){ print("day is : " + weekDay_solar[i]) } } }else{ print("day is : " + weekDay_solar[0]) } } } }
نکــته : در هنگام تعریف آرایه در زبان swift وقتی عناصر فارسی داخل آرایه تعریف می کنید باید دقت داشته باشید که عناصر فارسی از سمت راست index گزاری می شوند و اگر اشتباه نکنم این ویژگی در زبان برنامه نویسی جاوا بر عکس است .
سؤال از خودم بپرسم : آقای patriot می خوام ورودی را با استفاده از 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 : 1311/07/01
Month is : مهر
day is : جمعه
*/
موفق باشید
پاسخگویی و مشاهده پاسخ های این سوال تنها برای اعضای ویژه سایت امکان پذیر است .
چنانچه تمایل دارید به همه بخش ها دسترسی داشته باشید میتوانید از این بخش لایسنس این آموزش را خریداری نمایید .