diff --git a/SoluDate.xcodeproj/project.pbxproj b/SoluDate.xcodeproj/project.pbxproj
index afacb5e..9cfb514 100644
--- a/SoluDate.xcodeproj/project.pbxproj
+++ b/SoluDate.xcodeproj/project.pbxproj
@@ -454,6 +454,7 @@
B58CA6FE1EBF157200F03677 /* Release */,
);
defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
diff --git a/SoluDate/Info.plist b/SoluDate/Info.plist
index fbe1e6b..68c0384 100644
--- a/SoluDate/Info.plist
+++ b/SoluDate/Info.plist
@@ -20,5 +20,9 @@
$(CURRENT_PROJECT_VERSION)
NSPrincipalClass
+ UILaunchStoryboardName
+ LaunchScreen
+ UIMainStoryboardFile
+ Main
diff --git a/SoluDate/SoluDate.swift b/SoluDate/SoluDate.swift
index e890f72..1f85802 100644
--- a/SoluDate/SoluDate.swift
+++ b/SoluDate/SoluDate.swift
@@ -5,30 +5,16 @@
import Foundation
-public class LuDate {
- public var day: Int
- public var month: Int
- public var year: Int
- public var leap: Int
-
- public init(day: Int, month: Int, year: Int, leap: Int = 0) {
- self.day = day
- self.month = month
- self.year = year
- self.leap = leap
- }
-}
-
public class SoluDateConverter {
fileprivate static let PI = Double.pi
- fileprivate static func juliusDaysFromDate(_ dd: Int, _ mm: Int, _ yy: Int) -> Int {
- let a:Int = (14 - mm) / 12
- let y:Int = yy+4800-a
- let m:Int = mm+12*a-3
- var jd:Int = dd + (153*m+2)/5 + 365*y + y/4 - y/100 + y/400 - 32045
+ fileprivate static func juliusDaysFromDate(_ day: Int, _ month: Int, _ year: Int) -> Int {
+ let a:Int = (14 - month) / 12
+ let y:Int = year + 4800 - a
+ let m:Int = month + 12 * a - 3
+ var jd:Int = day + (153 * m + 2)/5 + 365 * y + y/4 - y/100 + y/400 - 32045
if (jd < 2299161) {
- jd = dd + (153*m+2)/5 + 365*y + y/4 - 32083
+ jd = day + (153 * m + 2)/5 + 365 * y + y/4 - 32083
}
return jd
@@ -38,20 +24,20 @@ public class SoluDateConverter {
var a: Int = 0
var b: Int = 0
var c: Int = 0
- if (jd > 2299160) { // After 5/10/1582, Gregorian calendar
+ if (jd > 2299160) {
a = jd + 32044
- b = (4*a+3)/146097
- c = a - (b*146097)/4
+ b = (4 * a + 3)/146097
+ c = a - (b * 146097)/4
} else {
b = 0
c = jd + 32082
}
- let d: Int = (4*c+3)/1461
- let e: Int = c - (1461*d)/4
- let m: Int = (5*e+2)/153
- let day: Int = e - (153*m+2)/5 + 1
- let month: Int = m + 3 - 12*(m/10)
- let year: Int = b*100 + d - 4800 + m/10
+ let d: Int = (4 * c + 3)/1461
+ let e: Int = c - (1461 * d)/4
+ let m: Int = (5 * e + 2)/153
+ let day: Int = e - (153 * m + 2)/5 + 1
+ let month: Int = m + 3 - 12 * (m/10)
+ let year: Int = b * 100 + d - 4800 + m/10
return [day, month, year]
}
@@ -60,47 +46,47 @@ public class SoluDateConverter {
}
fileprivate static func sunLongitude(_ jdn: Double) -> Double {
- //return CC2K.sunLongitude(jdn)
return sunLongitudeAA98(jdn)
}
fileprivate static func sunLongitudeAA98(_ jdn: Double) -> Double {
- let T: Double = (jdn - 2451545.0 ) / 36525 // Time in Julian centuries from 2000-01-01 12:00:00 GMT
- let T2: Double = T*T
- let dr: Double = SoluDateConverter.PI/180 // degree to radian
- let M: Double = 357.52910 + 35999.05030*T - 0.0001559*T2 - 0.00000048*T*T2 // mean anomaly, degree
- let L0: Double = 280.46645 + 36000.76983*T + 0.0003032*T2 // mean longitude, degree
- var DL: Double = (1.914600 - 0.004817*T - 0.000014*T2)*sin(dr*M)
- DL = DL + (0.019993 - 0.000101*T)*sin(dr*2*M) + 0.000290*sin(dr*3*M)
- var L: Double = L0 + DL // true longitude, degree
- L = L - 360*(Double(INT(L/360))) // Normalize to (0, 360)
+ let T: Double = (jdn - 2451545.0 ) / 36525
+ let T2: Double = T * T
+ let dr: Double = SoluDateConverter.PI/180
+ let M: Double = 357.52910 + 35999.05030 * T - 0.0001559 * T2 - 0.00000048 * T * T2
+ let L0: Double = 280.46645 + 36000.76983 * T + 0.0003032 * T2
+ var DL: Double = (1.914600 - 0.004817 * T - 0.000014 * T2) * sin(dr * M)
+ DL = DL + (0.019993 - 0.000101 * T) * sin(dr * 2 * M) + 0.000290 * sin(dr * 3 * M)
+ var L: Double = L0 + DL
+ L = L - 360 * (Double(INT(L/360)))
return L
}
fileprivate static func newMoonAA98(_ k: Int) -> Double {
- let T: Double = Double(k)/1236.85 // Time in Julian centuries from 1900 January 0.5
+ let T: Double = Double(k)/1236.85
let T2: Double = T * T
let T3: Double = T2 * T
let dr: Double = SoluDateConverter.PI/180
- var Jd1: Double = 2415020.75933 + 29.53058868*Double(k) + 0.0001178*T2 - 0.000000155*T3
- Jd1 = Jd1 + 0.00033*sin((166.56 + 132.87*T - 0.009173*T2)*dr)
- let M: Double = 359.2242 + 29.10535608*Double(k) - 0.0000333*T2 - 0.00000347*T3
- let Mpr: Double = 306.0253 + 385.81691806*Double(k) + 0.0107306*T2 + 0.00001236*T3 // Moon's mean anomaly
- let F: Double = 21.2964 + 390.67050646*Double(k) - 0.0016528*T2 - 0.00000239*T3 // Moon's argument of latitude
- var C1: Double = (0.1734 - 0.000393*T)*sin(M*dr) + 0.0021*sin(2*dr*M)
- C1 = C1 - 0.4068*sin(Mpr*dr) + 0.0161*sin(dr*2*Mpr)
- C1 = C1 - 0.0004*sin(dr*3*Mpr)
- C1 = C1 + 0.0104*sin(dr*2*F) - 0.0051*sin(dr*(M+Mpr))
- C1 = C1 - 0.0074*sin(dr*(M-Mpr)) + 0.0004*sin(dr*(2*F+M))
- C1 = C1 - 0.0004*sin(dr*(2*F-M)) - 0.0006*sin(dr*(2*F+Mpr))
- C1 = C1 + 0.0010*sin(dr*(2*F-Mpr)) + 0.0005*sin(dr*(2*Mpr+M))
+ var Jd1: Double = 2415020.75933 + 29.53058868 * Double(k) + 0.0001178 * T2 - 0.000000155 * T3
+ Jd1 = Jd1 + 0.00033 * sin((166.56 + 132.87 * T - 0.009173 * T2) * dr)
+ let M: Double = 359.2242 + 29.10535608 * Double(k) - 0.0000333 * T2 - 0.00000347 * T3
+ let Mpr: Double = 306.0253 + 385.81691806 * Double(k) + 0.0107306 * T2 + 0.00001236 * T3
+ let F: Double = 21.2964 + 390.67050646 * Double(k) - 0.0016528 * T2 - 0.00000239 * T3
+ var C1: Double = (0.1734 - 0.000393 * T) * sin(M * dr) + 0.0021 * sin(2 * dr * M)
+
+ C1 = C1 - 0.4068 * sin(Mpr*dr) + 0.0161 * sin(dr * 2*Mpr)
+ C1 = C1 - 0.0004 * sin(dr * 3 * Mpr)
+ C1 = C1 + 0.0104 * sin(dr * 2 * F) - 0.0051 * sin(dr * (M + Mpr))
+ C1 = C1 - 0.0074 * sin(dr * (M - Mpr)) + 0.0004 * sin(dr * (2 * F + M))
+ C1 = C1 - 0.0004 * sin(dr * (2 * F - M)) - 0.0006 * sin(dr * (2 * F + Mpr))
+ C1 = C1 + 0.0010 * sin(dr * (2 * F - Mpr)) + 0.0005 * sin(dr * (2 * Mpr + M))
var deltat: Double = 0
if (T < -11) {
- deltat = 0.001 + 0.000839*T + 0.0002261*T2 - 0.00000845*T3 - 0.000000081*T*T3
+ deltat = 0.001 + 0.000839 * T + 0.0002261 * T2 - 0.00000845 * T3 - 0.000000081 * T * T3
} else {
- deltat = -0.000278 + 0.000265*T + 0.000262*T2
+ deltat = -0.000278 + 0.000265 * T + 0.000262 * T2
}
let JdNew: Double = Jd1 + C1 - deltat
@@ -109,7 +95,6 @@ public class SoluDateConverter {
}
fileprivate static func newMoon(_ k:Int) -> Double {
- //return CC2K.newMoonTime(k)
return newMoonAA98(k)
}
@@ -122,8 +107,8 @@ public class SoluDateConverter {
return INT(jd + 0.5 + timeZone/24)
}
- fileprivate static func getLunarMonth11(_ yy: Int, _ timeZone: Double) -> Int {
- let off: Double = Double(juliusDaysFromDate(31, 12, yy)) - 2415021.076998695
+ fileprivate static func getLunarMonth11(_ year: Int, _ timeZone: Double) -> Int {
+ let off: Double = Double(juliusDaysFromDate(31, 12, year)) - 2415021.076998695
let k: Int = INT(off / 29.530588853)
var nm: Int = getNewMoonDay(k, timeZone)
let sunLong: Int = INT(getSunLongitude(nm, timeZone)/30)
@@ -135,38 +120,38 @@ public class SoluDateConverter {
fileprivate static func getLeapMonthOffset(_ a11: Int,_ timeZone: Double) -> Int {
let k: Int = INT(0.5 + (Double(a11) - 2415021.076998695) / 29.530588853)
- var last: Int = 0 // Month 11 contains point of sun longutide 3*PI/2 (December solstice)
- var i: Int = 1 // We start with the month following lunar month 11
- var arc: Int = INT(getSunLongitude(getNewMoonDay(k+i, timeZone), timeZone)/30)
+ var last: Int = 0
+ var i: Int = 1
+ var arc: Int = INT(getSunLongitude(getNewMoonDay(k + i, timeZone), timeZone)/30)
repeat {
last = arc
i = i + 1
- arc = INT(getSunLongitude(getNewMoonDay(k+i, timeZone), timeZone)/30)
+ arc = INT(getSunLongitude(getNewMoonDay(k + i, timeZone), timeZone)/30)
} while (arc != last && i < 14)
return i-1
}
- fileprivate static func convertSolar2Lunar(_ dd: Int,_ mm: Int,_ yy: Int,_ timeZone: Double) -> [Int] {
+ fileprivate static func convertSolar2Lunar(_ day: Int, _ month: Int, _ year: Int, _ timeZone: Double) -> [Int] {
var lunarDay: Int = 0
var lunarMonth: Int = 0
var lunarYear: Int = 0
var lunarLeap: Int = 0
- let dayNumber: Int = juliusDaysFromDate(dd, mm, yy)
+ let dayNumber: Int = juliusDaysFromDate(day, month, year)
let k: Int = INT((Double(dayNumber) - 2415021.076998695) / 29.530588853)
var monthStart: Int = getNewMoonDay(k+1, timeZone)
if (monthStart > dayNumber) {
monthStart = getNewMoonDay(k, timeZone)
}
- var a11: Int = getLunarMonth11(yy, timeZone)
+ var a11: Int = getLunarMonth11(year, timeZone)
var b11: Int = a11
if (a11 >= monthStart) {
- lunarYear = yy
- a11 = getLunarMonth11(yy-1, timeZone)
+ lunarYear = year
+ a11 = getLunarMonth11(year - 1, timeZone)
} else {
- lunarYear = yy+1
- b11 = getLunarMonth11(yy+1, timeZone)
+ lunarYear = year + 1
+ b11 = getLunarMonth11(year + 1, timeZone)
}
lunarDay = dayNumber-monthStart+1
let diff: Int = INT((Double(monthStart) - Double(a11))/29)
@@ -192,7 +177,8 @@ public class SoluDateConverter {
return [lunarDay, lunarMonth, lunarYear, lunarLeap]
}
- fileprivate static func convertLunar2Solar(_ lunarDay: Int,_ lunarMonth: Int,_ lunarYear: Int,_ lunarLeap: Int,_ timeZone: Double) -> [Int]? {
+ fileprivate static func convertLunar2Solar(_ lunarDay: Int,_ lunarMonth: Int,_ lunarYear: Int,_ lunarLeap: Int,
+ _ timeZone: Double) -> [Int]? {
var a11: Int = 0
var b11: Int = 0
if (lunarMonth < 11) {
@@ -223,15 +209,54 @@ public class SoluDateConverter {
return dateFromJuliusDays(monthStart+lunarDay-1)
}
+
+ fileprivate static func leapFromDate(_ day: Int,_ month: Int,_ year: Int) -> Int {
+ var lunarDay: Int = 0
+ var lunarMonth: Int = 0
+ var lunarYear: Int = 0
+ var lunarLeap: Int = 0
+ let timeZone: Double = 0
+ let dayNumber: Int = juliusDaysFromDate(day, month, year)
+ let k: Int = INT((Double(dayNumber) - 2415021.076998695) / 29.530588853)
+ var monthStart: Int = getNewMoonDay(k+1, timeZone)
+ if (monthStart > dayNumber) {
+ monthStart = getNewMoonDay(k, timeZone)
+ }
+ var a11: Int = getLunarMonth11(year, timeZone)
+ var b11: Int = a11
+ if (a11 >= monthStart) {
+ lunarYear = year
+ a11 = getLunarMonth11(year-1, timeZone)
+ } else {
+ lunarYear = year+1
+ b11 = getLunarMonth11(year+1, timeZone)
+ }
+ lunarDay = dayNumber-monthStart+1
+ let diff: Int = INT((Double(monthStart) - Double(a11))/29)
+ lunarLeap = 0
+ lunarMonth = diff + 11
+
+ if (b11 - a11 > 365) {
+ let leapMonthDiff: Int = getLeapMonthOffset(a11, timeZone)
+ if (diff >= leapMonthDiff) {
+ lunarMonth = diff + 10
+ if (diff == leapMonthDiff) {
+ lunarLeap = 1
+ }
+ }
+ }
+
+ return lunarLeap
+ }
}
extension SoluDateConverter {
- public static func lunarDateFromSonarDate(_ date: Date) -> LuDate {
+ public static func lunarDateFromSonarDate(_ date: Date) -> Date? {
let comps: DateComponents = Calendar.current.dateComponents([.day, .month, .year, .timeZone], from: date)
let day = comps.day!
let month = comps.month!
let year = comps.year!
- let rawComs = convertSolar2Lunar(day, month, year, 0.0)
+ let rawComs = convertSolar2Lunar(day, month, year, 7.0)
var lunarComps = DateComponents()
lunarComps.day = rawComs[0]
lunarComps.month = rawComs[1]
@@ -239,26 +264,33 @@ extension SoluDateConverter {
lunarComps.year = rawComs[2]
let leap = rawComs[3]
lunarComps.isLeapMonth = Bool(leap as NSNumber)
-
- let lunarDate: LuDate = LuDate(day: rawComs[0], month: rawComs[1], year: rawComs[2], leap: rawComs[3])
-
- return lunarDate
+
+ let date = NSCalendar(identifier: NSCalendar.Identifier.gregorian)?.date(from: lunarComps as DateComponents)
+
+ return date
}
- public static func sonarDateFromLunarDate(_ date: LuDate) -> Date? {
- let rawComs = convertLunar2Solar(date.day, date.month, date.year, date.leap, 7.0)
- guard let rawSonarComps = rawComs else {
- return nil
+ public static func sonarDateFromLunarDate(_ date: Date) -> Date? {
+ let comps: DateComponents = Calendar.current.dateComponents([.day, .month, .year, .timeZone], from: date)
+ let day = comps.day!
+ let month = comps.month!
+ let year = comps.year!
+ let leap = leapFromDate(day, month, year)
+ let jdComps = convertLunar2Solar(day, month, year, leap, 7.0)
+
+ var date: Date?
+
+ if let jdComps = jdComps {
+ let c = NSDateComponents()
+ c.day = jdComps[0]
+ c.month = jdComps[1]
+ c.year = jdComps[2]
+
+ date = NSCalendar(identifier: NSCalendar.Identifier.gregorian)?.date(from: c as DateComponents)
+ } else {
+ date = nil
}
- var sonarComps: DateComponents = DateComponents()
- sonarComps.day = rawSonarComps[0]
- sonarComps.month = rawSonarComps[1]
- sonarComps.year = rawSonarComps[2]
- let leap = rawSonarComps[3]
- sonarComps.isLeapMonth = Bool(leap as NSNumber)
-
- let sonarDate: Date? = sonarComps.date
-
- return sonarDate
+
+ return date
}
}
diff --git a/SoluDate/ViewController.swift b/SoluDate/ViewController.swift
index ffb694b..42c20be 100644
--- a/SoluDate/ViewController.swift
+++ b/SoluDate/ViewController.swift
@@ -14,15 +14,25 @@ class ViewController: UIViewController {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
- let date = SoluDateConverter.lunarDateFromSonarDate(Date())
- print("date \(date.day) \(date.month) \(date.year)")
+ let c = NSDateComponents()
+ c.day = 12
+ c.month = 4
+ c.year = 2017
+
+ let lunarDate = NSCalendar(identifier: NSCalendar.Identifier.gregorian)?.date(from: c as DateComponents)
+
+ let sonarDate = SoluDateConverter.sonarDateFromLunarDate(lunarDate!)
+
+ print(sonarDate)
+
+ let date = SoluDateConverter.lunarDateFromSonarDate(sonarDate!)
+ print("Lunar date \(date)")
+
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
-
-
}