├── .gitignore
├── LICENSE
├── Package.swift
├── README.md
├── Sources
└── SwiftLunar
│ ├── BrassMonkeys.swift
│ ├── Buddhis.swift
│ ├── BuddhistFestival.swift
│ ├── DogDays.swift
│ ├── ExactDate.swift
│ ├── Holiday.swift
│ ├── JieQi.swift
│ ├── Lunar.swift
│ ├── LunarMonth.swift
│ ├── LunarTime.swift
│ ├── LunarYear.swift
│ ├── NineStar.swift
│ ├── Solar.swift
│ ├── SolarHalfYear.swift
│ ├── SolarMonth.swift
│ ├── SolarSeason.swift
│ ├── SolarWeek.swift
│ ├── SolarYear.swift
│ ├── Taoist.swift
│ ├── TaoistFestival.swift
│ ├── Timeset.swift
│ ├── Timeset
│ ├── DaYun.swift
│ ├── LiuNian.swift
│ ├── LiuYue.swift
│ ├── XiaoYun.swift
│ └── Yun.swift
│ └── Utils
│ ├── BuddhistUtil.swift
│ ├── HolidayUtil.swift
│ ├── LunarUtil.swift
│ ├── ShouXingUtil.swift
│ ├── SolarUtil.swift
│ └── TaoistUtil.swift
└── Tests
└── SwiftLunarTests
├── BrassMonkeysTests.swift
├── BuddhisTests.swift
├── ConstellationTests.swift
├── CycleVoid.swift
├── DateTests.swift
├── DogDaysTests.swift
├── FestivalTests.swift
├── HalfYearTests.swift
├── HolidayTestst.swift
├── JulianDayTests.swift
├── LiuYaoTests.swift
├── LunarTests.swift
├── LunarYearTests.swift
├── MonthTests.swift
├── PhenologyTests.swift
├── SessonTests.swift
├── ShouXingUtilTests.swift
├── SolarTermsTests.swift
├── SolarTests.swift
├── SolarWeekTests.swift
├── TaoistTests.swift
├── TimeTests.swift
├── TimesetTests.swift
├── WeekTests.swift
├── YearTests.swift
└── YunTests.swift
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | Packages/
41 | # Package.pins
42 | # Package.resolved
43 | *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 | .DS_Store
92 | .netrc
93 |
94 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2021 6tail
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.6
2 | // The swift-tools-version declares the minimum version of Swift required to build this package.
3 |
4 | import PackageDescription
5 |
6 | let package = Package(
7 | name: "SwiftLunar",
8 | products: [
9 | // Products define the executables and libraries a package produces, and make them visible to other packages.
10 | .library(
11 | name: "SwiftLunar",
12 | targets: ["SwiftLunar"]),
13 | ],
14 | dependencies: [
15 | // Dependencies declare other packages that this package depends on.
16 | // .package(url: /* package url */, from: "1.0.0"),
17 | ],
18 | targets: [
19 | // Targets are the basic building blocks of a package. A target can define a module or a test suite.
20 | // Targets can depend on other targets in this package, and on products in packages this package depends on.
21 | .target(
22 | name: "SwiftLunar",
23 | dependencies: []),
24 | .testTarget(
25 | name: "SwiftLunarTests",
26 | dependencies: ["SwiftLunar"]),
27 | ]
28 | )
29 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # lunar [](https://github.com/bestheme/lunar-swift/blob/main/LICENSE)
2 |
3 |
4 | lunar是一款无第三方依赖的日历工具,支持公历(阳历)、农历(阴历、老黄历)、道历、佛历,支持星座、儒略日、干支、生肖、节气、节日、时间局、五行、法定节假日及调休等。
5 |
6 |
7 |
8 | ## 示例
9 |
10 | import SwiftLunar
11 |
12 |
13 | //今天
14 | //let date: Lunar = Lunar(fromDate: Date());
15 |
16 | //指定阴历的某一天
17 | let date: Lunar = Lunar(fromYmd: 1986, month: 4, day: 21)
18 | print(date.toFullString())
19 | print(date.getSolar().toFullString())
20 |
21 |
22 | 输出结果:
23 |
24 | 一九八六年四月廿一 丙寅(虎)年 癸巳(蛇)月 癸酉(鸡)日 子(鼠)时 纳音[炉中火 长流水 剑锋金 桑柘木] 星期四 北方玄武 星宿[斗木獬](吉) 彭祖百忌[癸不词讼理弱敌强 酉不会客醉坐颠狂] 喜神方位[巽](东南) 阳贵神方位[巽](东南) 阴贵神方位[震](正东) 福神方位[兑](正西) 财神方位[离](正南) 冲[(丁卯)兔] 煞[东]
25 | 1986-05-29 00:00:00 星期四 双子座
26 |
27 |
28 | 感谢 [6tail](https://github.com/6tail)
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/BrassMonkeys.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrassMonkeys.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 | // 数九
8 | // Brass Monkeys
9 |
10 | public struct BrassMonkeys {
11 | /// 名称,如一九、二九
12 | public var name: String;
13 |
14 | /// 当前数九第几天,1-9
15 | public var index: Int = 1;
16 |
17 | public func toString() -> String{
18 | return "\(name)"
19 | }
20 |
21 | public func toFullString() -> String {
22 | return "\(name)第\(index)天"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Buddhis.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Buddhis.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 | // 佛历
8 | @available(watchOS 8.0, *)
9 | @available(iOS 15.0, *)
10 | @available(macOS 12.0, *)
11 | public struct Buddhis {
12 | static let DEAD_YEAR: Int = -543;
13 |
14 | /// 阴历
15 | public var lunarOfBuddhis: Lunar;
16 |
17 | public init(lunar: Lunar) {
18 | self.lunarOfBuddhis = lunar
19 | }
20 |
21 | public init(year: Int, month: Int, day: Int, hour: Int = 0, minute: Int = 0, second: Int = 0) {
22 | let y: Int = year + Buddhis.DEAD_YEAR - 1
23 | self.lunarOfBuddhis = Lunar(fromYmdHms: y, lunarMonth: month, lunarDay: day, hour: hour, minute: minute, second: second)
24 | }
25 |
26 |
27 | public var year: Int {
28 | get {
29 | let sy: Int = lunarOfBuddhis.getSolar().year;
30 | var y: Int = sy - Buddhis.DEAD_YEAR;
31 | if (sy == lunarOfBuddhis.year) {
32 | y += 1;
33 | }
34 | return y;
35 | }
36 | }
37 |
38 | public var month: Int {
39 | get {
40 | return lunarOfBuddhis.month
41 | }
42 | }
43 |
44 | public var day: Int {
45 | get {
46 | return lunarOfBuddhis.day
47 | }
48 | }
49 |
50 | public var yearInChinese: String {
51 | let y: String = "\(year)"
52 | var s: String = ""
53 | for v in y.utf16 {
54 | s += LunarUtil.NUMBER[Int(v) - 48]
55 | }
56 | return s;
57 | }
58 |
59 | public var monthInChinese: String {
60 | get {
61 | return lunarOfBuddhis.getMonthInChinese()
62 | }
63 | }
64 |
65 | public var dayInChinese: String {
66 | get {
67 | return lunarOfBuddhis.getDayInChinese()
68 | }
69 | }
70 |
71 | public var festivals: [BuddhistFestival] {
72 | var l: [BuddhistFestival] = [];
73 | let fs: [BuddhistFestival]? = BuddhistUtil.FESTIVAL["\(month)-\(day)"]
74 | if (nil != fs) {
75 | l.append(contentsOf: fs!)
76 | }
77 | return l;
78 | }
79 |
80 | public var isMonthZhai: Bool {
81 | get {
82 | let m: Int = month;
83 | return 1 == m || 5 == m || 9 == m;
84 | }
85 | }
86 |
87 | public var isDayYangGong: Bool {
88 | get {
89 | for festival in festivals {
90 | if ("杨公忌" == festival.name) {
91 | return true;
92 | }
93 | }
94 | return false
95 | }
96 | }
97 |
98 | public var isDayZhaiShuoWang: Bool {
99 | get {
100 | let d: Int = day
101 | return 1 == d || 15 == d
102 | }
103 | }
104 |
105 | public var isDayZhaiSix: Bool {
106 | get {
107 | let d: Int = day
108 | if (8 == d || 14 == d || 15 == d || 23 == d || 29 == d || 30 == d) {
109 | return true
110 | } else if (28 == d) {
111 | let m: LunarMonth? = LunarMonth.fromYm(lunarYear: lunarOfBuddhis.year, lunarMonth: month)!
112 | return nil != m && 30 != m!.dayCount
113 | }
114 | return false;
115 | }
116 | }
117 |
118 | public var isDayZhaiTen: Bool {
119 | get {
120 | let d: Int = day
121 | return 1 == d ||
122 | 8 == d ||
123 | 14 == d ||
124 | 15 == d ||
125 | 18 == d ||
126 | 23 == d ||
127 | 24 == d ||
128 | 28 == d ||
129 | 29 == d ||
130 | 30 == d
131 | }
132 | }
133 |
134 | public var isDayZhaiGuanYin: Bool {
135 | get {
136 | let k: String = "\(month)-\(day)"
137 | for d in BuddhistUtil.DAY_ZHAI_GUAN_YIN {
138 | if (k == d) {
139 | return true;
140 | }
141 | }
142 | return false;
143 | }
144 | }
145 |
146 | var xiu: String {
147 | get {
148 | return BuddhistUtil.getXiu(month: month, day: day)
149 | }
150 | }
151 |
152 | var xiuLuck: String {
153 | get {
154 | return LunarUtil.XIU_LUCK[xiu]!
155 | }
156 | }
157 |
158 | var xiuSong: String {
159 | get {
160 | return LunarUtil.XIU_SONG[xiu]!
161 | }
162 | }
163 |
164 | var zheng: String {
165 | return LunarUtil.ZHENG[xiu]!
166 | }
167 |
168 | var animal: String {
169 | get {
170 | return LunarUtil.ANIMAL[xiu]!
171 | }
172 | }
173 |
174 | var gong: String {
175 | get {
176 | return LunarUtil.GONG[xiu]!
177 | }
178 | }
179 |
180 | var shou: String {
181 | get {
182 | return LunarUtil.SHOU[gong]!
183 | }
184 | }
185 |
186 |
187 | func toString() -> String {
188 | return "\(yearInChinese)年\(monthInChinese)月\(dayInChinese)"
189 | }
190 |
191 | func toFullString() -> String {
192 | var s: String = toString()
193 | for festival in festivals {
194 | s += " ("
195 | s += festival.toString()
196 | s += ")"
197 | }
198 | return s;
199 | }
200 | }
201 |
202 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/BuddhistFestival.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BuddhistFestival.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 | // 佛历因果犯忌
8 |
9 | public struct BuddhistFestival {
10 | /// 是日何日,如:雷斋日
11 | public var name: String?
12 |
13 | /// 犯之因果,如:犯者夺纪
14 | public var result: String?
15 |
16 | /// 是否每月同
17 | public var everyMonth: Bool?
18 |
19 | /// 备注,如:宜先一日即戒
20 | public var remark: String?
21 |
22 | public init(name: String, result: String = "", everyMonth: Bool = false, remark: String = "") {
23 | self.name = name;
24 | self.result = result
25 | self.everyMonth = everyMonth
26 | self.remark = remark
27 | }
28 |
29 | public func isEveryMonth() -> Bool {
30 | return everyMonth!
31 | }
32 |
33 | func toString() -> String {
34 | return "\(name!)"
35 | }
36 |
37 | func toFullString() -> String {
38 | var s: String = "\(name!)"
39 | if (nil != result && result!.count > 0) {
40 | s += " ";
41 | s += result!
42 | }
43 | if (nil != remark && remark!.count > 0) {
44 | s += " "
45 | s += remark!
46 | }
47 | return s
48 | }
49 | }
50 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/DogDays.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/21.
6 | //
7 | // Dog days
8 | //
从夏至后第3个庚日算起,初伏为10天,中伏为10天或20天,末伏为10天。当夏至与立秋之间出现4个庚日时中伏为10天,出现5个庚日则为20天。
9 |
10 | public struct DogDays {
11 | /// 名称:初伏、中伏、末伏
12 | public var name: String?;
13 |
14 | /// 当前入伏第几天,1-20
15 | public var index: Int = 1;
16 |
17 | public func toString() -> String{
18 | return "\(name ?? "")"
19 | }
20 |
21 | public func toFullString() -> String {
22 | return "\(name ?? "")第\(index)天"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/ExactDate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExactDate.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/11.
6 | //
7 |
8 | import Foundation
9 |
10 | /// 精确日期
11 | /// @author 6tail
12 | struct ExactDate {
13 |
14 | static func fromYmd(year: Int, month: Int, day: Int) -> Date {
15 | return fromYmdHms(year: year, month: month, day: day, hour: 0, minute: 0, second: 0);
16 | }
17 |
18 | static func fromYmdHms(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) -> Date {
19 | let dc = DateComponents(calendar: Calendar(identifier: .gregorian), year: year, month: month, day: day, hour: hour, minute: minute, second: second)
20 | return dc.date!
21 | }
22 |
23 | static func fromDate(date: Date) -> Date {
24 | let dc = Calendar(identifier: .gregorian).dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
25 | return fromYmdHms(year:
26 | dc.year!, month: dc.month!, day: dc.day!, hour: dc.hour!, minute: dc.minute!, second: dc.second!)
27 | }
28 |
29 | /// 获取两个日期之间相差的天数(如果日期a比日期b小,天数为正,如果日期a比日期b大,天数为负)
30 | ///
31 | /// @param ay 年a
32 | /// @param am 月a
33 | /// @param ad 日a
34 | /// @param by 年b
35 | /// @param bm 月b
36 | /// @param bd 日b
37 | /// @return 天数
38 | static func getDaysBetween(ay: Int, am: Int, ad: Int, by: Int, bm: Int, bd: Int) -> Int {
39 | let calendar = Calendar.current
40 | let startDate = fromYmd(year: ay, month: am, day: ad)
41 | let endDate = fromYmd(year: by, month: bm, day: bd)
42 | let diff: DateComponents = calendar.dateComponents([.day], from: startDate, to: endDate)
43 | return diff.day!
44 | }
45 |
46 | /// 获取两个日期之间相差的天数(如果日期a比日期b小,天数为正,如果日期a比日期b大,天数为负)
47 | ///
48 | /// @param calendar0 日期a
49 | /// @param calendar1 日期b
50 | /// @return 天数
51 | static func getDaysBetweenDate(startDate: Date, endDate: Date) -> Int {
52 | let calendar = Calendar.current
53 | let diff: DateComponents = calendar.dateComponents([.day], from: startDate, to: endDate)
54 | return diff.day!
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Holiday.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Holiday.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/12.
6 | //
7 |
8 | import Foundation
9 |
10 | //节假日
11 |
12 | struct Holiday {
13 | // 日期,YYYY/MM/DD格式
14 | var day: String?
15 |
16 | // 名称,如:国庆
17 | var name: String?
18 |
19 | // 是否调休,即是否要上班
20 | var isWork: Bool = false
21 |
22 | // 关联的节日,YYYY/MM/DD格式
23 | var target: String?
24 |
25 | init(day: String, name: String, work: Bool, target: String) {
26 | // if (!day.contains('-')) {
27 | // day = day.substring(0, 4) +
28 | // '-' +
29 | // day.substring(4, 6) +
30 | // '-' +
31 | // day.substring(6);
32 | // } else {
33 | self.day = day
34 | // }
35 | self.name = name
36 | self.isWork = work
37 | // if (!target.contains('-')) {
38 | // _target = target.substring(0, 4) +
39 | // '-' +
40 | // target.substring(4, 6) +
41 | // '-' +
42 | // target.substring(6);
43 | // } else {
44 | self.target = target
45 | // }
46 | }
47 |
48 | // String getDay() => _day!;
49 |
50 | // void setDay(String day) {
51 | // _day = day;
52 | // }
53 |
54 | // String getName() => _name!;
55 | //
56 | // void setName(String name) {
57 | // _name = name;
58 | // }
59 |
60 | // bool isWork() => _work;
61 | //
62 | // void setWork(bool work) {
63 | // _work = work;
64 | // }
65 |
66 | // String getTarget() => _target!;
67 | //
68 | // void setTarget(String target) {
69 | // _target = target;
70 | // }
71 |
72 |
73 | func toString() -> String {
74 | return "\(String(describing: day)) \(String(describing: name))\((isWork) ? "调休" : "") \(String(describing: target))"
75 | }
76 | }
77 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/JieQi.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JieQI.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 | // Solar terms
8 | @available(watchOS 8.0, *)
9 | @available(iOS 15.0, *)
10 | @available(macOS 12.0, *)
11 | public struct JieQi {
12 | static let JIE_QI: [String] = [
13 | "冬至",
14 | "小寒",
15 | "大寒",
16 | "立春",
17 | "雨水",
18 | "惊蛰",
19 | "春分",
20 | "清明",
21 | "谷雨",
22 | "立夏",
23 | "小满",
24 | "芒种",
25 | "夏至",
26 | "小暑",
27 | "大暑",
28 | "立秋",
29 | "处暑",
30 | "白露",
31 | "秋分",
32 | "寒露",
33 | "霜降",
34 | "立冬",
35 | "小雪",
36 | "大雪"
37 | ];
38 |
39 | /// 名称
40 | public var name: String? {
41 | didSet {
42 | for i in 0.. _name!;
69 |
70 | // void setName(String name) {
71 | // _name = name;
72 | // for (int i = 0, j = JIE_QI.length; i < j; i++) {
73 | // if (name == JIE_QI[i]) {
74 | // if (i % 2 == 0) {
75 | // _qi = true;
76 | // } else {
77 | // _jie = true;
78 | // }
79 | // return;
80 | // }
81 | // }
82 | // }
83 |
84 | // Solar getSolar() => _solar!;
85 |
86 | // void setSolar(Solar solar) {
87 | // _solar = solar;
88 | // }
89 |
90 | // bool isJie() => _jie;
91 | //
92 | // bool isQi() => _qi;
93 |
94 | public func toString() -> String {
95 | return String(describing: name)
96 | }
97 | }
98 |
99 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/LunarMonth.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LunarMonth.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/12.
6 | //
7 |
8 | import Foundation
9 |
10 | // 农历月
11 | @available(watchOS 8.0, *)
12 | @available(iOS 15.0, *)
13 | @available(macOS 12.0, *)
14 | public struct LunarMonth {
15 | /// 农历年
16 | public var year: Int = 0
17 |
18 | /// 农历月:1-12,闰月为负数,如闰2月为-2
19 | public var month: Int = 0
20 |
21 | /// 天数,大月30天,小月29天
22 | public var dayCount: Int = 0
23 |
24 | /// 初一的儒略日
25 | public var firstJulianDay: Double = 0
26 |
27 | public init(year: Int, month: Int, dayCount: Int, firstJulianDay: Double) {
28 | self.year = year
29 | self.month = month
30 | self.dayCount = dayCount
31 | self.firstJulianDay = firstJulianDay
32 | }
33 |
34 |
35 | static func fromYm(lunarYear: Int, lunarMonth: Int) -> LunarMonth? {
36 | return LunarYear.fromYear(lunarYear: lunarYear).getMonth(lunarMonth: lunarMonth)
37 | }
38 |
39 | public func getYear() -> Int {
40 | return year
41 | }
42 |
43 | public func getMonth() -> Int {
44 | return month
45 | }
46 |
47 | public func getDayCount() -> Int {
48 | return dayCount
49 | }
50 |
51 | public func getFirstJulianDay() -> Double {
52 | return firstJulianDay
53 | }
54 |
55 | public func isLeap() -> Bool {
56 | return month < 0
57 | }
58 |
59 | func getPositionTaiSui() -> String {
60 | var p: String = ""
61 | let m: Int = abs(month)
62 | switch (m) {
63 | case 1: break
64 | case 5: break
65 | case 9:
66 | p = "艮"
67 | break
68 | case 3: break
69 | case 7: break
70 | case 11:
71 | p = "坤"
72 | break
73 | case 4: break
74 | case 8: break
75 | case 12:
76 | p = "巽"
77 | break
78 | default:
79 | p = LunarUtil.POSITION_GAN[Solar(fromJulianDay: self.getFirstJulianDay())
80 | .getLunar()
81 | .getMonthGanIndex()]
82 | }
83 | return p
84 | }
85 |
86 | func getPositionTaiSuiDesc() -> String {
87 | return LunarUtil.POSITION_DESC[getPositionTaiSui()]!
88 | }
89 |
90 | // func getNineStar() -> NineStar {
91 | // var index: Int = LunarYear(lunarYear: year).getZhiIndex() % 3
92 | // var m: Int = abs(month)
93 | // var monthZhiIndex: Int = (13 + m) % 12
94 | // var n: Int = 27 - (index * 3)
95 | // if (monthZhiIndex < LunarUtil.BASE_MONTH_ZHI_INDEX) {
96 | // n -= 3
97 | // }
98 | // var offset: Int = (n - monthZhiIndex) % 9
99 | // return NineStar.fromIndex(offset)
100 | // }
101 |
102 | func toString() -> String {
103 | let month: String = LunarUtil.MONTH[abs(month)]
104 | return "\(year)年\(isLeap() ? "闰" : "")\(month)月(\(dayCount))天"
105 | }
106 |
107 | func next(n: Int) -> LunarMonth{
108 | if (0 == n) {
109 | return LunarMonth.fromYm(lunarYear: year, lunarMonth: month)!
110 | } else if (n > 0) {
111 | var rest: Int = n
112 | var ny: Int = year
113 | var iy: Int = ny
114 | var im: Int = month
115 | var index: Int = 0
116 | var months: [LunarMonth] = LunarYear(lunarYear: ny).getMonths()
117 | while (true) {
118 | let size: Int = months.count
119 | for i in 0.. Int {
32 | return ganIndex
33 | }
34 |
35 | public func getZhiIndex() -> Int {
36 | return zhiIndex
37 | }
38 |
39 | public func getShengXiao() -> String {
40 | return LunarUtil.SHENGXIAO[zhiIndex + 1]
41 | }
42 |
43 | public func getGan() -> String {
44 | return LunarUtil.GAN[ganIndex + 1]
45 | }
46 |
47 | public func getZhi() -> String {
48 | return LunarUtil.ZHI[zhiIndex + 1]
49 | }
50 |
51 | public func getGanZhi() -> String {
52 | return "\(getGan())\(getZhi())"
53 | }
54 |
55 | func getPositionXi() -> String {
56 | return LunarUtil.POSITION_XI[ganIndex + 1]
57 | }
58 |
59 | func getPositionXiDesc() -> String {
60 | return LunarUtil.POSITION_DESC[getPositionXi()]!
61 | }
62 |
63 | func getPositionYangGui() -> String {
64 | return LunarUtil.POSITION_YANG_GUI[ganIndex + 1]
65 | }
66 |
67 | func getPositionYangGuiDesc() -> String {
68 | return LunarUtil.POSITION_DESC[getPositionYangGui()]!
69 | }
70 |
71 | func getPositionYinGui() -> String {
72 | return LunarUtil.POSITION_YIN_GUI[ganIndex + 1]
73 | }
74 |
75 | func getPositionYinGuiDesc() -> String {
76 | return LunarUtil.POSITION_DESC[getPositionYinGui()]!
77 | }
78 |
79 | func getPositionFu(geren: Int = 1) -> String {
80 | return (1 == geren
81 | ? LunarUtil.POSITION_FU
82 | : LunarUtil.POSITION_FU_2)[ganIndex + 1]
83 | }
84 |
85 | func getPositionFuDesc(geren: Int = 1 ) -> String {
86 | return LunarUtil.POSITION_DESC[getPositionFu(geren: geren)]!
87 | }
88 |
89 | func getPositionCai() -> String {
90 | return LunarUtil.POSITION_CAI[ganIndex + 1]
91 | }
92 |
93 | func getPositionCaiDesc() -> String {
94 | return LunarUtil.POSITION_DESC[getPositionCai()]!
95 | }
96 |
97 | func getNaYin() -> String {
98 | return LunarUtil.NAYIN[getGanZhi()]!
99 | }
100 |
101 | func getTianShen() -> String {
102 | let dayZhi: String = lunar!.getDayZhiExact()
103 | let offset: Int = LunarUtil.ZHI_TIAN_SHEN_OFFSET[dayZhi]!
104 | return LunarUtil.TIAN_SHEN[(zhiIndex + offset) % 12 + 1]
105 | }
106 |
107 | func getTianShenType() -> String {
108 | return LunarUtil.TIAN_SHEN_TYPE[getTianShen()]!
109 | }
110 |
111 | func getTianShenLuck() -> String {
112 | return LunarUtil.TIAN_SHEN_TYPE_LUCK[getTianShenType()]!
113 | }
114 |
115 | public func getChong() -> String {
116 | return LunarUtil.CHONG[zhiIndex]
117 | }
118 |
119 | func getSha() -> String {
120 | return LunarUtil.SHA[getZhi()]!
121 | }
122 |
123 | func getChongShengXiao() -> String {
124 | let chong: String = getChong()
125 | for i in 0.. String {
134 | "(\(getChongGan())\(getChong()))\(getChongShengXiao())"
135 | }
136 |
137 | public func getChongGan() -> String {
138 | return LunarUtil.CHONG_GAN[ganIndex]
139 | }
140 |
141 | func getChongGanTie() -> String {
142 | return LunarUtil.CHONG_GAN_TIE[ganIndex]
143 | }
144 |
145 | func getYi() -> [String] {
146 | return LunarUtil.getTimeYi(dayGanZhi: lunar!.getDayInGanZhiExact(), timeGanZhi: getGanZhi())
147 | }
148 |
149 | func getJi() -> [String] {
150 | return LunarUtil.getTimeJi(dayGanZhi: lunar!.getDayInGanZhiExact(), timeGanZhi: getGanZhi())
151 | }
152 |
153 | // func getNineStar() -> NineStar {
154 | // //顺逆
155 | // String solarYmd = _lunar!.getSolar().toYmd()
156 | // Map jieQi = _lunar!.getJieQiTable()
157 | // bool asc = false
158 | // if (solarYmd.compareTo(jieQi["冬至"]!.toYmd()) >= 0 &&
159 | // solarYmd.compareTo(jieQi["夏至"]!.toYmd()) < 0) {
160 | // asc = true
161 | // }
162 | // int start = asc ? 7 : 3
163 | // String dayZhi = _lunar!.getDayZhi()
164 | // if ("子午卯酉".contains(dayZhi)) {
165 | // start = asc ? 1 : 9
166 | // } else if ("辰戌丑未".contains(dayZhi)) {
167 | // start = asc ? 4 : 6
168 | // }
169 | // int index = asc ? start + _zhiIndex - 1 : start - _zhiIndex - 1
170 | // if (index > 8) {
171 | // index -= 9
172 | // }
173 | // if (index < 0) {
174 | // index += 9
175 | // }
176 | // return NineStar(index)
177 | // }
178 |
179 |
180 | func toString() -> String {
181 | return getGanZhi()
182 | }
183 |
184 | public func getXun() -> String {
185 | return LunarUtil.getXun(ganZhi: getGanZhi())
186 | }
187 |
188 | public func getXunKong() -> String {
189 | return LunarUtil.getXunKong(ganZhi: getGanZhi())
190 | }
191 |
192 | func getMinHm() -> String {
193 | var hour: Int = lunar!.hour
194 | if (hour < 1) {
195 | return "00:00"
196 | } else if (hour > 22) {
197 | return "23:00"
198 | }
199 | if (hour % 2 == 0) {
200 | hour -= 1
201 | }
202 | return "\(hour < 10 ? "0" : "")\(hour):00"
203 | }
204 |
205 | func getMaxHm() -> String {
206 | var hour: Int = lunar!.hour
207 | if (hour < 1) {
208 | return "00:59"
209 | } else if (hour > 22) {
210 | return "23:59"
211 | }
212 | if (hour % 2 != 0) {
213 | hour += 1
214 | }
215 | return "\(hour < 10 ? "0" : "")\(hour):59"
216 | }
217 | }
218 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/NineStar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // NineStar.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/21.
6 | //
7 | // 九星
8 | // 玄空九星、奇门九星都来源于北斗九星,九数、七色、五行、后天八卦方位都是相通的。
9 | //
10 | struct NineStar {
11 | /// 九数
12 | static let NUMBER: [String] = [
13 | "一",
14 | "二",
15 | "三",
16 | "四",
17 | "五",
18 | "六",
19 | "七",
20 | "八",
21 | "九"
22 | ];
23 |
24 | /// 七色
25 | static let COLOR: [String] = [
26 | "白",
27 | "黒",
28 | "碧",
29 | "绿",
30 | "黄",
31 | "白",
32 | "赤",
33 | "白",
34 | "紫"
35 | ];
36 |
37 | /// 五行
38 | static let WU_XING: [String] = [
39 | "水",
40 | "土",
41 | "木",
42 | "木",
43 | "土",
44 | "金",
45 | "金",
46 | "土",
47 | "火"
48 | ];
49 |
50 | /// 后天八卦方位
51 | static let POSITION: [String] = [
52 | "坎",
53 | "坤",
54 | "震",
55 | "巽",
56 | "中",
57 | "乾",
58 | "兑",
59 | "艮",
60 | "离"
61 | ];
62 |
63 | /// 北斗九星
64 | static let NAME_BEI_DOU: [String] = [
65 | "天枢",
66 | "天璇",
67 | "天玑",
68 | "天权",
69 | "玉衡",
70 | "开阳",
71 | "摇光",
72 | "洞明",
73 | "隐元"
74 | ];
75 |
76 | /// 玄空九星(玄空风水)
77 | static let NAME_XUAN_KONG: [String] = [
78 | "贪狼",
79 | "巨门",
80 | "禄存",
81 | "文曲",
82 | "廉贞",
83 | "武曲",
84 | "破军",
85 | "左辅",
86 | "右弼"
87 | ];
88 |
89 | /// 奇门九星(奇门遁甲,也称天盘九星)
90 | static let NAME_QI_MEN: [String] = [
91 | "天蓬",
92 | "天芮",
93 | "天冲",
94 | "天辅",
95 | "天禽",
96 | "天心",
97 | "天柱",
98 | "天任",
99 | "天英"
100 | ];
101 |
102 | /// 八门(奇门遁甲)
103 | static let BA_MEN_QI_MEN: [String] = [
104 | "休",
105 | "死",
106 | "伤",
107 | "杜",
108 | "",
109 | "开",
110 | "惊",
111 | "生",
112 | "景"
113 | ];
114 |
115 | /// 太乙九神(太乙神数)
116 | static let NAME_TAI_YI: [String] = [
117 | "太乙",
118 | "摄提",
119 | "轩辕",
120 | "招摇",
121 | "天符",
122 | "青龙",
123 | "咸池",
124 | "太阴",
125 | "天乙"
126 | ];
127 |
128 | /// 太乙九神对应类型
129 | static let TYPE_TAI_YI: [String] = [
130 | "吉神",
131 | "凶神",
132 | "安神",
133 | "安神",
134 | "凶神",
135 | "吉神",
136 | "凶神",
137 | "吉神",
138 | "吉神"
139 | ];
140 |
141 | /// 太乙九神歌诀(太乙神数)
142 | static let SONG_TAI_YI: [String] = [
143 | "门中太乙明,星官号贪狼,赌彩财喜旺,婚姻大吉昌,出入无阻挡,参谒见贤良,此行三五里,黑衣别阴阳。",
144 | "门前见摄提,百事必忧疑,相生犹自可,相克祸必临,死门并相会,老妇哭悲啼,求谋并吉事,尽皆不相宜,只可藏隐遁,若动伤身疾。",
145 | "出入会轩辕,凡事必缠牵,相生全不美,相克更忧煎,远行多不利,博彩尽输钱,九天玄女法,句句不虚言。",
146 | "招摇号木星,当之事莫行,相克行人阻,阴人口舌迎,梦寐多惊惧,屋响斧自鸣,阴阳消息理,万法弗违情。",
147 | "五鬼为天符,当门阴女谋,相克无好事,行路阻中途,走失难寻觅,道逢有尼姑,此星当门值,万事有灾除。",
148 | "神光跃青龙,财气喜重重,投入有酒食,赌彩最兴隆,更逢相生旺,休言克破凶,见贵安营寨,万事总吉同。",
149 | "吾将为咸池,当之尽不宜,出入多不利,相克有灾情,赌彩全输尽,求财空手回,仙人真妙语,愚人莫与知,动用虚惊退,反复逆风吹。",
150 | "坐临太阴星,百祸不相侵,求谋悉成就,知交有觅寻,回风归来路,恐有殃伏起,密语中记取,慎乎莫轻行。",
151 | "迎来天乙星,相逢百事兴,运用和合庆,茶酒喜相迎,求谋并嫁娶,好合有天成,祸福如神验,吉凶甚分明。"
152 | ];
153 |
154 | /// 吉凶(玄空风水)
155 | static let LUCK_XUAN_KONG: [String] = [
156 | "吉",
157 | "凶",
158 | "凶",
159 | "吉",
160 | "凶",
161 | "吉",
162 | "凶",
163 | "吉",
164 | "吉"
165 | ];
166 |
167 | /// 吉凶(奇门遁甲)
168 | static let LUCK_QI_MEN: [String] = [
169 | "大凶",
170 | "大凶",
171 | "小吉",
172 | "大吉",
173 | "大吉",
174 | "大吉",
175 | "小凶",
176 | "小吉",
177 | "小凶"
178 | ];
179 |
180 | /// 阴阳(奇门遁甲)
181 | static let YIN_YANG_QI_MEN: [String] = [
182 | "阳",
183 | "阴",
184 | "阳",
185 | "阳",
186 | "阳",
187 | "阴",
188 | "阴",
189 | "阳",
190 | "阴"
191 | ];
192 |
193 | /// 序号,0到8
194 | var index: Int = 0;
195 |
196 | var number: String {
197 | get {
198 | return NineStar.NUMBER[index]
199 | }
200 | }
201 |
202 | var color: String {
203 | get {
204 | return NineStar.COLOR[index]
205 | }
206 | }
207 |
208 | var wuXing: String {
209 | get {
210 | return NineStar.WU_XING[index]
211 | }
212 | }
213 |
214 | var position: String {
215 | get {
216 | return NineStar.POSITION[index]
217 | }
218 | }
219 |
220 | var positionDesc: String? {
221 | get {
222 | return LunarUtil.POSITION_DESC[position]
223 | }
224 | }
225 |
226 | var nameInXuanKong: String {
227 | get {
228 | return NineStar.NAME_XUAN_KONG[index]
229 | }
230 | }
231 |
232 | var nameInBeiDou: String {
233 | get {
234 | return NineStar.NAME_BEI_DOU[index]
235 | }
236 | }
237 |
238 | var nameInQiMen: String {
239 | get {
240 | return NineStar.NAME_QI_MEN[index]
241 | }
242 | }
243 |
244 | var nameInTaiYi: String {
245 | get {
246 | return NineStar.NAME_TAI_YI[index]
247 | }
248 | }
249 |
250 | var luckInQiMen: String {
251 | get {
252 | return NineStar.LUCK_QI_MEN[index]
253 | }
254 | }
255 |
256 | var luckInXuanKong: String {
257 | get {
258 | return NineStar.LUCK_XUAN_KONG[index]
259 | }
260 | }
261 |
262 | var yinYangInQiMen: String {
263 | get {
264 | return NineStar.YIN_YANG_QI_MEN[index]
265 | }
266 | }
267 |
268 | var typeInTaiYi: String {
269 | get {
270 | return NineStar.TYPE_TAI_YI[index]
271 | }
272 | }
273 |
274 | var baMenInQiMen: String {
275 | get {
276 | NineStar.BA_MEN_QI_MEN[index]
277 | }
278 | }
279 |
280 | var songInTaiYi: String {
281 | get {
282 | NineStar.SONG_TAI_YI[index]
283 | }
284 | }
285 |
286 |
287 |
288 | func toString() -> String {
289 | return "\(number)\(color)\(wuXing)\(nameInBeiDou)"
290 | }
291 |
292 | func toFullString() -> String {
293 | var s: String =
294 | "\(number)\(color)\(wuXing) \(position)(\(positionDesc ?? ""))\(nameInBeiDou) 玄空[\(nameInXuanKong) \(luckInXuanKong)] 奇门[\(nameInQiMen) \(luckInQiMen)"
295 | if (baMenInQiMen.count > 0) {
296 | s += " \(baMenInQiMen)门"
297 | }
298 | s += " \(yinYangInQiMen)] 太乙[\(nameInTaiYi) \(typeInTaiYi)]"
299 | return s;
300 | }
301 | }
302 |
303 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Solar.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Solar.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/11.
6 | //
7 |
8 | import Foundation
9 |
10 | // 阳历日期
11 |
12 | @available(watchOS 8.0, *)
13 | @available(iOS 15.0, *)
14 | @available(macOS 12.0, *)
15 | public struct Solar: Hashable {
16 | static let J2000: Double = 2451545
17 |
18 | public var year: Int = 0
19 |
20 | public var month: Int = 0
21 |
22 | public var day: Int = 0
23 |
24 | public var hour: Int = 0
25 |
26 | public var minute: Int = 0
27 |
28 | public var second:Int = 0
29 |
30 | public var isLeapYear: Bool {
31 | return SolarUtil.isLeapYear(year: self.year)
32 | }
33 |
34 | public var calendar: Date {
35 | get {
36 | // let dc = DateComponents(calendar: Calendar(identifier: .gregorian), year: year, month: month, day: day, hour: hour, minute: minute, second: second)
37 | return ExactDate.fromYmdHms(year: year, month: month, day: day, hour: hour, minute: minute, second: second)
38 | }
39 | set (date) {
40 | let setDate: Date = ExactDate.fromDate(date: date)
41 | // let dateCompment: DateComponents = Calendar(identifier: .gregorian).dateComponents([.year, .month, .day, .hour, .minute, .second], from: date)
42 | year = setDate.get(.year) //dateCompment.year!
43 | month = setDate.get(.month) //dateCompment.month!
44 | day = calcDay(day: setDate.get(.day))
45 | hour = setDate.get(.hour) //dateCompment.hour!
46 | minute = setDate.get(.minute) // dateCompment.minute!
47 | second = setDate.get(.second) //dateCompment.second!
48 | }
49 | }
50 |
51 | public var julianDay: Double {
52 | get {
53 | var y: Int = year
54 | var m: Int = month
55 | let d: Double = Double(day) + ((Double(second) * 1.0 / 60 + Double(minute)) / 60 + Double(hour)) / 24
56 | var n: Int = 0
57 | var g: Bool = false
58 | if (y * 372 + m * 31 + Int(floor(d)) >= 588829) {
59 | g = true
60 | }
61 | if (m <= 2) {
62 | m += 12
63 | y -= 1
64 | }
65 | if (g) {
66 | n = Int(floor(Double(y) * 1.0 / 100))
67 | n = 2 - n + Int(floor(Double(n) * 1.0 / 4))
68 | }
69 | return floor(365.25 * (Double(y) + 4716)) +
70 | floor(30.6001 * (Double(m) + 1)) +
71 | d +
72 | Double(n) -
73 | 1524.5
74 | }
75 | set (julianDay) {
76 | var d: Int = Int(floor(julianDay + 0.5))
77 | var f: Double = julianDay + 0.5 - Double(d)
78 | var c: Double
79 |
80 | if (d >= 2299161) {
81 | c = floor((Double(d) - 1867216.25) / 36524.25)
82 | d += Int(1 + c - floor(c * 1.0 / 4))
83 | }
84 | d += 1524
85 | var year: Int = Int(floor((Double(d) - 122.1) / 365.25))
86 | d -= Int(floor(365.25 * Double(year)))
87 | var month: Int = Int(floor(Double(d) * 1.0 / 30.601))
88 | d -= Int(floor(30.601 * Double(month)))
89 | let day: Int = d
90 | if (month > 13) {
91 | month -= 13
92 | year -= 4715
93 | } else {
94 | month -= 1
95 | year -= 4716
96 | }
97 | f *= 24
98 | var hour: Int = Int(floor(f))
99 |
100 | f -= Double(hour)
101 | f *= 60
102 | var minute: Int = Int(floor(f))
103 |
104 | f -= Double(minute)
105 | f *= 60
106 | var second: Int = Int(round(f))
107 |
108 | if (second > 59) {
109 | second -= 60
110 | minute += 1
111 | }
112 | if (minute > 59) {
113 | minute -= 60
114 | hour += 1
115 | }
116 |
117 | self.year = Int(year)
118 | self.month = Int(month)
119 | self.day = calcDay(day: Int(day))
120 | self.hour = Int(hour)
121 | self.minute = Int(minute)
122 | self.second = Int(second)
123 | }
124 | }
125 |
126 | public init(fromYmd year: Int, month: Int, day: Int) {
127 | self.year = year
128 | self.month = month
129 | self.day = calcDay(day: day)
130 | }
131 |
132 | public init(fromYmdHms year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) {
133 | self.year = year
134 | self.month = month
135 | self.day = calcDay(day: day)
136 | self.hour = hour
137 | self.minute = minute
138 | self.second = second
139 | }
140 |
141 | public init() {
142 | let date: Date = Date()
143 | self.calendar = date
144 | }
145 |
146 | public init(fromDate date: Date) {
147 | self.calendar = date
148 | }
149 |
150 | public init(fromJulianDay julianDay: Double) {
151 | self.julianDay = julianDay
152 | }
153 |
154 | // init(fromJulianDay julianDay: Double) {
155 | // var d: Double = (julianDay + 0.5)
156 | // var f: Double = julianDay + 0.5 - d
157 | // var c: Double
158 | //
159 | // if (d >= 2299161) {
160 | // c = ((d - 1867216.25) / 36524.25)
161 | // d += 1 + c - (c * 1.0 / 4)
162 | // }
163 | // d += 1524
164 | // var year: Double = ((d - 122.1) / 365.25)
165 | // d -= (365.25 * year)
166 | // var month: Double = (d * 1.0 / 30.601)
167 | // d -= (30.601 * month)
168 | // var day: Double = d
169 | // if (month > 13) {
170 | // month -= 13
171 | // year -= 4715
172 | // } else {
173 | // month -= 1
174 | // year -= 4716
175 | // }
176 | // f *= 24
177 | // var hour: Double = f
178 | //
179 | // f -= hour
180 | // f *= 60
181 | // var minute: Double = f
182 | //
183 | // f -= minute
184 | // f *= 60
185 | // var second: Double = f
186 | //
187 | // if (second > 59) {
188 | // second -= 60
189 | // minute += 1
190 | // }
191 | // if (minute > 59) {
192 | // minute -= 60
193 | // hour += 1
194 | // }
195 | //
196 | // self.calendar = ExactDate.fromYmdHms(year, month, day, hour, minute, second)
197 | // self.year = calendar.get(.year)
198 | // self.month = calendar.get(.month)
199 | // self.day = calendar.get(.day)
200 | // self.hour = calendar.get(.hour)
201 | // self.minute = calendar.get(.minute)
202 | // self.second = calendar.get(.second)
203 | // }
204 |
205 | // static List? getSolarfromBaZi(
206 | // {required String yearGanZhi,
207 | // required String monthGanZhi,
208 | // required String dayGanZhi,
209 | // required String timeGanZhi,
210 | // int sect = 2,
211 | // int baseYear = 1900,
212 | // int endYear = 2100}) {
213 | // List? l = []
214 | // Solar today = Solar.fromDate(DateTime(endYear))
215 | // Lunar lunar = today.getLunar()
216 | //
217 | // int offsetYear = LunarUtil.getJiaZiIndex(lunar.getYearInGanZhiExact()) -
218 | // LunarUtil.getJiaZiIndex(yearGanZhi)
219 | // if (offsetYear < 0) {
220 | // offsetYear = offsetYear + 60
221 | // }
222 | // int startYear = lunar.getYear() - offsetYear
223 | // int hour = 0
224 | // String timeZhi = timeGanZhi.substring(1)
225 | // for (int i = 0, j = LunarUtil.ZHI.length i < j i++) {
226 | // if (LunarUtil.ZHI[i] == timeZhi) {
227 | // hour = (i - 1) * 2
228 | // }
229 | // }
230 | // while (startYear >= baseYear) {
231 | // int year = startYear - 1
232 | // int counter = 0
233 | // int month = 12
234 | // int day
235 | // bool found = false
236 | // while (counter < 15) {
237 | // if (year >= baseYear) {
238 | // day = 1
239 | // Solar solar = Solar.fromYmdHms(year, month, day, hour, 0, 0)
240 | // lunar = solar.getLunar()
241 | // if (lunar.getYearInGanZhiExact() == yearGanZhi &&
242 | // lunar.getMonthInGanZhiExact() == monthGanZhi) {
243 | // found = true
244 | // break
245 | // }
246 | // }
247 | // month++
248 | // if (month > 12) {
249 | // month = 1
250 | // year++
251 | // }
252 | // counter++
253 | // }
254 | //
255 | // if (found) {
256 | // counter = 0
257 | // month--
258 | // if (month < 1) {
259 | // month = 12
260 | // year--
261 | // }
262 | // day = 1
263 | // Solar solar = Solar.fromYmdHms(year, month, day, hour, 0, 0)
264 | // while (counter < 61) {
265 | // lunar = solar.getLunar()
266 | // String dgz = (2 == sect)
267 | // ? lunar.getDayInGanZhiExact2()
268 | // : lunar.getDayInGanZhiExact()
269 | // if (lunar.getYearInGanZhiExact() == yearGanZhi &&
270 | // lunar.getMonthInGanZhiExact() == monthGanZhi &&
271 | // dgz == dayGanZhi &&
272 | // lunar.getTimeInGanZhi() == timeGanZhi) {
273 | // l.add(solar)
274 | // break
275 | // }
276 | // solar = solar.next(1)
277 | // counter ++
278 | // }
279 | // }
280 | // startYear -= 60
281 | // }
282 | // return l
283 | // }
284 |
285 | // int getYear() => _year //get method
286 | //
287 | // int getMonth() => _month
288 | //
289 | // int getDay() => _day
290 | //
291 | // int getHour() => _hour
292 | //
293 | // int getMinute() => _minute
294 | //
295 | // int getSecond() => _second
296 | //
297 | // DateTime getCalendar() => _calendar!
298 |
299 |
300 | func toString() -> String {
301 | return toYmd()
302 | }
303 |
304 |
305 | // func isLeapYear() -> Bool {
306 | // return SolarUtil.isLeapYear(year: year)
307 | // }
308 |
309 | // 获取星期,0代表周日,1代表周一
310 | // @return 0123456
311 | public var week: Int {
312 | var w: Int = Calendar(identifier: .gregorian).component(.weekday, from: calendar) - 1
313 | if (w == -1) {
314 | w = 0
315 | }
316 | return w
317 | }
318 |
319 | // 获取星期的中文
320 | // @return 日一二三四五六
321 | public var weekInChinese: String {
322 | return SolarUtil.WEEK[week]
323 | }
324 |
325 | /// 获取星座
326 | /// @return 星座
327 | public var constellation: String {
328 | var index: Int = 11
329 | let y: Int = month * 100 + day
330 | if (y >= 321 && y <= 419) {
331 | index = 0
332 | } else if (y >= 420 && y <= 520) {
333 | index = 1
334 | } else if (y >= 521 && y <= 621) {
335 | index = 2
336 | } else if (y >= 622 && y <= 722) {
337 | index = 3
338 | } else if (y >= 723 && y <= 822) {
339 | index = 4
340 | } else if (y >= 823 && y <= 922) {
341 | index = 5
342 | } else if (y >= 923 && y <= 1023) {
343 | index = 6
344 | } else if (y >= 1024 && y <= 1122) {
345 | index = 7
346 | } else if (y >= 1123 && y <= 1221) {
347 | index = 8
348 | } else if (y >= 1222 || y <= 119) {
349 | index = 9
350 | } else if (y <= 218) {
351 | index = 10
352 | }
353 | return SolarUtil.XING_ZUO[index]
354 | }
355 |
356 | /// 获取儒略日
357 | /// @return 儒略日
358 | // func getJulianDay() -> Double{
359 | // var y: Int = year
360 | // var m: Int = month
361 | // var d: Double = day + ((second * 1.0 / 60 + minute) / 60 + hour) / 24
362 | // var n: Int = 0
363 | // var g: Bool = false
364 | // if (y * 372 + m * 31 + d.floor() >= 588829) {
365 | // g = true
366 | // }
367 | // if (m <= 2) {
368 | // m += 12
369 | // y -= 1
370 | // }
371 | // if (g) {
372 | // n = (y * 1.0 / 100).floor()
373 | // n = 2 - n + (n * 1.0 / 4).floor()
374 | // }
375 | // return ((365.25 * (y + 4716)).floor()) +
376 | // ((30.6001 * (m + 1)).floor()) +
377 | // d +
378 | // n -
379 | // 1524.5
380 | // }
381 |
382 | /// 获取节日,有可能一天会有多个节日
383 | /// @return 劳动节等
384 | public var festivals: [String] {
385 | var l: [String] = []
386 | //获取几月几日对应的节日
387 | var f: String? = SolarUtil.FESTIVAL["\(month)-\(day)"]
388 | if (nil != f) {
389 | l.append(f!)
390 | }
391 | //计算几月第几个星期几对应的节日
392 | let weeks: Int = Int(ceil(Double(day) / 7.0))
393 | //星期几,1代表星期天
394 | // let week: Int = eek()
395 | f = SolarUtil.WEEK_FESTIVAL["\(month)-\(weeks)-\(week)"]
396 | if (nil != f) {
397 | l.append(f!)
398 | }
399 | if (day + 7 > SolarUtil.getDaysOfMonth(year: year, month: month)) {
400 | f = SolarUtil.WEEK_FESTIVAL["\(month)-0-\(week)"]
401 | if (nil != f) {
402 | l.append(f!)
403 | }
404 | }
405 | return l
406 | }
407 |
408 | func calcDay(day: Int) -> Int {
409 | var newDay: Int = day
410 | if (year == 1582 && month == 10) {
411 | if (newDay >= 15) {
412 | newDay -= 10
413 | return newDay
414 | }
415 | }
416 | return newDay
417 | }
418 | /// 获取非正式的节日,有可能一天会有多个节日
419 | /// @return 非正式的节日列表,如中元节
420 | public var otherFestivals: [String] {
421 | var l: [String] = []
422 | let fs: [String]? = SolarUtil.OTHER_FESTIVAL["\(month)-\(day)"]
423 | if (nil != fs) {
424 | l.append(contentsOf: fs!)
425 | }
426 | return l
427 | }
428 |
429 | /// 获取往后推几天的阳历日期,如果要往前推,则天数用负数
430 | /// @param days 天数
431 | /// @param onlyWorkday 是否仅限工作日
432 | /// @return 阳历日期
433 | public func next(days:Int, onlyWorkday: Bool = false) -> Solar {
434 | var c: Date = calendar
435 | let timeInterval: TimeInterval = Double(days * 86400)
436 | if (0 != days) {
437 | if (!onlyWorkday) {
438 | c.addTimeInterval(timeInterval)
439 | } else {
440 | var rest: Int = abs(days)
441 | let add: TimeInterval = days < 1 ? -86400 : 86400
442 | while (rest > 0) {
443 | c.addTimeInterval(add)
444 | var work: Bool = true
445 | let holiday: Holiday? =
446 | HolidayUtil.getHolidayByYmd(year: c.get(.year), month: c.get(.month), day: c.get(.day))
447 | if (nil == holiday) {
448 | let week: Int = Calendar(identifier: .gregorian).component(.weekday, from: c)
449 | if (1 == week || 7 == week) {
450 | work = false
451 | }
452 | } else {
453 | work = holiday!.isWork
454 | }
455 | if (work) {
456 | rest-=1
457 | }
458 | }
459 | }
460 | }
461 | return Solar(fromDate: c)
462 | }
463 |
464 | public func toYmd() -> String {
465 | var d: Int = day
466 | if (year == 1582 && month == 10) {
467 | if (d >= 5) {
468 | d += 10
469 | }
470 | }
471 | var y: String = Swift.String(year)
472 | while (y.count < 4) {
473 | y = "0" + y
474 | }
475 | let dateFormat = DateFormatter()
476 | dateFormat.dateFormat = "yyyy-MM-dd"
477 | return dateFormat.string(from: calendar)
478 | // return calendar.formatted(.dateTime.locale(Locale(identifier: "zh_HK")).year(.defaultDigits).month(.twoDigits).day(.twoDigits))
479 | }
480 |
481 | public func toYmdHms() -> String {
482 | let dateFormat = DateFormatter()
483 | dateFormat.dateFormat = "yyyy-MM-dd HH:mm:ss"
484 | return dateFormat.string(from: calendar)
485 | // return calendar.formatted(.dateTime.locale(Locale(identifier: "zh_CN")).year(.defaultDigits).month(.twoDigits).day(.twoDigits).hour(.twoDigits(amPM: .narrow)).minute(.twoDigits).second(.twoDigits))
486 | }
487 |
488 | public func toHm() -> String {
489 | let dateFormat = DateFormatter()
490 | dateFormat.dateFormat = "HH:mm"
491 | return dateFormat.string(from: calendar)
492 | // return calendar.formatted(.dateTime.locale(Locale(identifier: "zh_CN")).hour(.twoDigits(amPM: .narrow)).minute(.twoDigits))
493 | }
494 |
495 | func toFullString() -> String {
496 | var s: String = toYmdHms()
497 | if (isLeapYear) {
498 | s += " 闰年"
499 | }
500 | s += " 星期" + weekInChinese
501 | let festivals: [String] = festivals
502 | for festival in festivals {
503 | s += " (\(festival))"
504 | }
505 | s += " " + constellation + "座"
506 | return s
507 | }
508 |
509 | public func getLunar() -> Lunar {
510 | return Lunar(fromDate: calendar)
511 | }
512 | }
513 |
514 | extension Date {
515 | func get(_ components: Calendar.Component..., calendar: Calendar = Calendar.current) -> DateComponents {
516 | return calendar.dateComponents(Set(components), from: self)
517 | }
518 |
519 | func get(_ component: Calendar.Component, calendar: Calendar = Calendar.current) -> Int {
520 | return calendar.component(component, from: self)
521 | }
522 | }
523 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/SolarHalfYear.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarHalfYear.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 | import Foundation
8 |
9 | // 阳历半年
10 |
11 | @available(watchOS 8.0, *)
12 | @available(iOS 15.0, *)
13 | @available(macOS 12.0, *)
14 | struct SolarHalfYear {
15 | /// 半年的月数
16 | static let MONTH_COUNT: Int = 6;
17 |
18 | /// 年
19 | var year: Int = 0;
20 |
21 | /// 月
22 | var month: Int = 0;
23 |
24 | var index: Int {
25 | get {
26 | Int(ceil(Double(month) * 1.0 / Double(SolarHalfYear.MONTH_COUNT)))
27 | }
28 | }
29 |
30 | var months: [SolarMonth] {
31 | get {
32 | var l: [SolarMonth] = []
33 | let newIndex = self.index - 1
34 | for i in 0.. getMonths() {
59 | // List l = [];
60 | // int index = getIndex() - 1;
61 | // for (int i = 0; i < MONTH_COUNT; i++) {
62 | // l.add(SolarMonth.fromYm(_year, MONTH_COUNT * index + i + 1));
63 | // }
64 | // return l;
65 | // }
66 |
67 | func next(halfYears: Int) -> SolarHalfYear {
68 | if (0 == halfYears) {
69 | return SolarHalfYear(year: year, month: month);
70 | } else {
71 | var rest: Int = halfYears * SolarHalfYear.MONTH_COUNT;
72 | var y: Int = year;
73 | y += Int(rest / 12)
74 | rest = rest % 12;
75 | var m: Int = month + rest;
76 | if (m > 12) {
77 | y += 1;
78 | m -= 12;
79 | } else if (m < 1) {
80 | y -= 1;
81 | m += 12;
82 | }
83 | return SolarHalfYear(year: y, month: m);
84 | }
85 | }
86 |
87 | func toString() -> String {
88 | return "\(year).\(index)"
89 | }
90 |
91 | func toFullString() -> String {
92 | return "\(year)年\(index == 1 ? "上" : "下")半年"
93 | }
94 | }
95 |
96 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/SolarMonth.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarMonth.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 | import Foundation
8 |
9 | // 阳历月
10 |
11 | @available(watchOS 8.0, *)
12 | @available(iOS 15.0, *)
13 | @available(macOS 12.0, *)
14 | public struct SolarMonth {
15 | /// 年
16 | public var year: Int = 0;
17 |
18 | /// 月
19 | public var month: Int = 0;
20 |
21 | public var days: [Solar] {
22 | get {
23 | var l: [Solar] = [];
24 | let d: Solar = Solar(fromYmd: year, month: month, day: 1)
25 | l.append(d)
26 | let days: Int = SolarUtil.getDaysOfMonth(year: year, month: month);
27 | for i in 1.. _year;
58 |
59 | // int getMonth() => _month;
60 |
61 | // List getDays() {
62 | // List l = [];
63 | // Solar d = new Solar.fromYmd(_year, _month, 1);
64 | // l.add(d);
65 | // int days = SolarUtil.getDaysOfMonth(_year, _month);
66 | // for (int i = 1; i < days; i++) {
67 | // l.add(d.next(i));
68 | // }
69 | // return l;
70 | // }
71 |
72 | public func next(quantity: Int) -> SolarMonth {
73 | if (0 == quantity) {
74 | return SolarMonth(year: year, month: month);
75 | } else {
76 | var rest: Int = quantity
77 | var y: Int = year;
78 | y += Int(rest / 12);
79 | rest = rest % 12;
80 | var m: Int = month + rest;
81 | if (m > 12) {
82 | y += 1;
83 | m -= 12;
84 | } else if (m < 1) {
85 | y -= 1;
86 | m += 12;
87 | }
88 | return SolarMonth(year: y, month: m);
89 | }
90 | }
91 |
92 |
93 | public func toString() -> String {
94 | return "\(year)-\(month)"
95 | }
96 |
97 | public func toFullString() -> String {
98 | return "\(year)年\(month)月"
99 | }
100 | }
101 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/SolarSeason.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarSeason.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/21.
6 | //
7 | import Foundation
8 |
9 | @available(watchOS 8.0, *)
10 | @available(iOS 15.0, *)
11 | @available(macOS 12.0, *)
12 | struct SolarSeason {
13 | /// 一季度的月数
14 | static let MONTH_COUNT: Int = 3;
15 |
16 | /// 年
17 | var year: Int = 0;
18 |
19 | /// 月
20 | var month: Int = 0;
21 |
22 |
23 | init(year: Int, month: Int) {
24 | self.year = year
25 | self.month = month
26 | }
27 |
28 | init(fromDate date: Date) {
29 | self.year = date.get(.year);
30 | self.month = date.get(.month)
31 | }
32 |
33 | var index: Int {
34 | get {
35 | return Int(ceil(Double(month) * 1.0 / Double(SolarSeason.MONTH_COUNT)))
36 | }
37 | }
38 |
39 | var months: [SolarMonth] {
40 | get {
41 | var months: [SolarMonth] = []
42 | let index = index - 1
43 | for i in 0.. SolarSeason {
51 | if (0 == seasons) {
52 | return self;
53 | } else {
54 | var rest: Int = seasons * SolarSeason.MONTH_COUNT
55 | var y: Int = year
56 | y += Int(floor(Double(rest) / 12))
57 | rest = abs(rest % 12);
58 | var m: Int = month + rest
59 | if (m > 12) {
60 | y += 1
61 | m -= 12
62 | } else if (m < 1) {
63 | y -= 1
64 | m += 12
65 | }
66 | return SolarSeason(year: y, month: m);
67 | }
68 | }
69 |
70 | func toString() -> String {
71 | return "\(year).\(index)"
72 | }
73 |
74 | func toFullString() -> String {
75 | return "\(year)年\(index)季度"
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/SolarWeek.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarWeek.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 |
8 | import Foundation
9 |
10 | // 阳历周
11 | @available(watchOS 8.0, *)
12 | @available(iOS 15.0, *)
13 | @available(macOS 12.0, *)
14 | public struct SolarWeek {
15 |
16 | private static let durationOfDay: Int = 86400
17 | /// 年
18 | public var year: Int = 0
19 |
20 | /// 月
21 | public var month: Int = 0
22 |
23 | /// 日
24 | public var day: Int = 0
25 |
26 | /// 星期几作为一周的开始,1234560分别代表星期一至星期天
27 | public var start: Int = 0
28 |
29 | var index: Int {
30 | get {
31 | let c: Date = ExactDate.fromYmd(year: year, month: month, day: 1)
32 | var firstDayWeek: Int = c.get(.weekday) - 1
33 | if (7 == firstDayWeek) {
34 | firstDayWeek = 0;
35 | }
36 | var offset: Int = firstDayWeek - start
37 | if (offset < 0) {
38 | offset += 7
39 | }
40 | return Int(ceil(Double(day + offset) / 7.0))
41 | }
42 | }
43 |
44 | public init(year: Int, month: Int, day: Int, start: Int) {
45 | self.year = year
46 | self.month = month
47 | self.day = day
48 | self.start = start
49 | }
50 |
51 | public init(date: Date = Date(), start: Int = 0) {
52 | self.year = date.get(.year)
53 | self.month = date.get(.month)
54 | self.day = date.get(.day)
55 | self.start = start
56 | }
57 |
58 | public func next(weeks: Int, separateMonth: Bool) -> SolarWeek {
59 | if (0 == weeks) {
60 | return SolarWeek(year: year, month: month, day: day, start: start)
61 | }
62 | if (separateMonth) {
63 | var n: Int = weeks
64 | var c: Date = ExactDate.fromYmd(year: year, month: month, day: day)
65 | var week: SolarWeek = SolarWeek(date: c, start: start)
66 | var month: Int = month;
67 | let plus: Bool = n > 0;
68 | while (0 != n) {
69 | c = c.addingTimeInterval(TimeInterval((plus ? 7 : -7) * 86400))
70 | week = SolarWeek(date: c, start: start);
71 | var weekMonth: Int = week.month;
72 | if (month != weekMonth) {
73 | let index: Int = week.index
74 | if (plus) {
75 | if (1 == index) {
76 | let firstDay: Solar = week.getFirstDay();
77 | week = SolarWeek(year: firstDay.year, month: firstDay.month,
78 | day: firstDay.day, start: start)
79 | weekMonth = week.month
80 | } else {
81 | c = ExactDate.fromYmd(year: week.year, month: week.month, day: 1);
82 | week = SolarWeek(date:c, start: start)
83 | }
84 | } else {
85 | let size: Int = SolarUtil.getWeeksOfMonth(year: week.year, month: week.month, start: start)
86 | if (size == index) {
87 | let firstDay: Solar = week.getFirstDay()
88 | let lastDay: Solar = firstDay.next(days: 6)
89 | week = SolarWeek(year: lastDay.year, month: lastDay.month,
90 | day: lastDay.day, start: start)
91 | weekMonth = week.month;
92 | } else {
93 | c = ExactDate.fromYmd(year: week.year, month: week.month,
94 | day: SolarUtil.getDaysOfMonth(year: week.year, month: week.month))
95 | week = SolarWeek(date:c, start: start)
96 | }
97 | }
98 | month = weekMonth
99 | }
100 | n -= plus ? 1 : -1;
101 | }
102 | return week
103 | } else {
104 | var c: Date = ExactDate.fromYmd(year: year, month: month, day: day)
105 | c = c.addingTimeInterval(TimeInterval(weeks * 7 * SolarWeek.durationOfDay))
106 | return SolarWeek(date:c, start: start)
107 | }
108 | }
109 |
110 | public func getFirstDay() -> Solar {
111 | var c: Date = ExactDate.fromYmd(year: year, month: month, day: day);
112 | var week: Int = c.get(.weekday) - 1
113 | if (week == -1) {
114 | week = 0;
115 | }
116 | var prev: Int = week - start
117 | if (prev < 0) {
118 | prev += 7;
119 | }
120 | c = c.addingTimeInterval(TimeInterval(-prev * SolarWeek.durationOfDay))
121 | return Solar(fromDate: c)
122 | }
123 |
124 | public func getFirstDayInMonth() -> Solar? {
125 | let days: [Solar] = getDays()
126 | for day in days {
127 | if (month == day.month) {
128 | return day
129 | }
130 | }
131 | return nil;
132 | }
133 |
134 | public func getDays() -> [Solar] {
135 | let firstDay: Solar = getFirstDay()
136 | var l: [Solar] = [];
137 | l.append(firstDay);
138 | for i in 1..<7 {
139 | l.append(firstDay.next(days: i))
140 | }
141 | return l
142 | }
143 |
144 | public func getDaysInMonth() -> [Solar] {
145 | let days: [Solar] = self.getDays()
146 | var l: [Solar] = []
147 | for day in days {
148 | if (month != day.month) {
149 | continue;
150 | }
151 | l.append(day)
152 | }
153 | return l;
154 | }
155 |
156 | // func getIndex() -> Int {
157 | // let c: Date = ExactDate.fromYmd(year: year, month: month, day: 1);
158 | // var firstDayWeek: Int = c.get(.weekday) - 1
159 | // if (7 == firstDayWeek) {
160 | // firstDayWeek = 0;
161 | // }
162 | // var offset: Int = firstDayWeek - start;
163 | // if (offset < 0) {
164 | // offset += 7
165 | // }
166 | // return Int(ceil(Double(day + offset) / 7.0))
167 | // }
168 |
169 | func getIndexInYear() -> Int {
170 | let c: Date = ExactDate.fromYmd(year: year, month: 1, day: 1);
171 | var firstDayWeek: Int = c.get(.weekday) - 1
172 | if (-1 == firstDayWeek) {
173 | firstDayWeek = 0
174 | }
175 | var offset: Int = firstDayWeek - start;
176 | if (offset < 0) {
177 | offset += 7
178 | }
179 | return Int(ceil(Double(SolarUtil.getDaysInYear(year: year, month: month, day: day) + offset) / 7.0))
180 |
181 | }
182 |
183 |
184 | func toString() -> String {
185 | return "\(year).\(month).\(index)"
186 | }
187 |
188 | func toFullString() -> String {
189 | return "\(year)年\(month)月第\(index)周"
190 | }
191 | }
192 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/SolarYear.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarYear.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/20.
6 | //
7 | import Foundation
8 | // 阳历年
9 | @available(watchOS 8.0, *)
10 | @available(iOS 15.0, *)
11 | @available(macOS 12.0, *)
12 | struct SolarYear {
13 | /// 一年的月数
14 | static let MONTH_COUNT: Int = 12;
15 |
16 | /// 年
17 | var year: Int = 0;
18 |
19 | init(year: Int) {
20 | self.year = year
21 | }
22 |
23 | init(date: Date = Date()) {
24 | self.year = ExactDate.fromDate(date: date).get(.year)
25 | }
26 |
27 | // SolarYear() : this.fromDate(DateTime.now());
28 | //
29 | // SolarYear.fromYear(int year) {
30 | // _year = year;
31 | // }
32 | //
33 | // SolarYear.fromDate(DateTime date) {
34 | // _year = ExactDate.fromDate(date).year;
35 | // }
36 |
37 | // int getYear() => _year;
38 |
39 | func getMonths() -> [SolarMonth] {
40 | var l: [SolarMonth] = []
41 | let m: SolarMonth = SolarMonth(year: year, month: 1)
42 | l.append(m);
43 | for i in 1.. SolarYear {
50 | return SolarYear(year: year + quantity)
51 | }
52 |
53 |
54 | func toString() -> String {
55 | return "\(year)"
56 | }
57 |
58 | func toFullString() -> String {
59 | return "\(year)年"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Taoist.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Taoist.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | @available(watchOS 8.0, *)
8 | @available(iOS 15.0, *)
9 | @available(macOS 12.0, *)
10 | struct Taoist {
11 | static let BIRTH_YEAR: Int = -2697
12 |
13 | /// 阴历
14 | var lunar: Lunar?
15 |
16 | static func fromLunar(lunar: Lunar) -> Taoist{
17 | return Taoist(lunar: lunar)
18 | }
19 |
20 | static func fromYmdHms(year: Int, month: Int, day: Int, hour: Int, minute: Int, second: Int) -> Taoist {
21 | return fromLunar(
22 | lunar: SwiftLunar.Lunar(fromYmdHms: year + BIRTH_YEAR, lunarMonth: month, lunarDay: day, hour: hour, minute: minute, second: second));
23 | }
24 |
25 | static func fromYmd(year: Int, month: Int, day: Int) -> Taoist {
26 | return fromYmdHms(year: year, month: month, day: day, hour: 0, minute: 0, second: 0);
27 | }
28 |
29 | var year: Int {
30 | get {
31 | return lunar!.year - Taoist.BIRTH_YEAR
32 | }
33 | }
34 |
35 | var month: Int {
36 | get {
37 | return lunar!.month
38 | }
39 | }
40 |
41 | var day: Int {
42 | get {
43 | return lunar!.day
44 | }
45 | }
46 |
47 | var yearInChinese: String {
48 | get {
49 | let y: String = Swift.String(year)
50 | var s: String = ""
51 | for v in y.utf16 {
52 | s += LunarUtil.NUMBER[Int(v) - 48]
53 | }
54 | return s
55 | }
56 | }
57 |
58 | var monthInChinese: String {
59 | get {
60 | return lunar!.getMonthInChinese()
61 | }
62 | }
63 |
64 | var dayInChinese: String {
65 | get {
66 | lunar!.getDayInChinese()
67 | }
68 | }
69 |
70 | func getFestivals() -> [TaoistFestival] {
71 | var l: [TaoistFestival] = [];
72 | let fs: [TaoistFestival]? = TaoistUtil.FESTIVAL["\(month)-\(day)"]
73 | if (nil != fs) {
74 | l.append(contentsOf: fs!)
75 | }
76 | let solarTerm: String = lunar!.getJieQi()
77 | if (solarTerm == "冬至") {
78 | l.append(TaoistFestival(name: "元始天尊圣诞"))
79 | } else if (solarTerm == "夏至") {
80 | l.append(TaoistFestival(name: "灵宝天尊圣诞"))
81 | }
82 | // 八节日
83 | var f: String? = TaoistUtil.BA_JIE[solarTerm]
84 | if (f != nil) {
85 | l.append(TaoistFestival(name: f!))
86 | }
87 | // 八会日
88 | f = TaoistUtil.BA_HUI[lunar!.getDayInGanZhi()]
89 | if (f != nil) {
90 | l.append(TaoistFestival(name: f!))
91 | }
92 | return l;
93 | }
94 |
95 | func isDayIn(days: [String]) -> Bool {
96 | let md: String = "\(month)-\(day)"
97 | for day in days {
98 | if (md == day) {
99 | return true;
100 | }
101 | }
102 | return false;
103 | }
104 |
105 | var isDaySanHuiL: Bool {
106 | get {
107 | return isDayIn(days: TaoistUtil.SAN_HUI)
108 | }
109 | }
110 |
111 | var isDaySanYuan: Bool {
112 | get {
113 | return isDayIn(days: TaoistUtil.SAN_YUAN)
114 | }
115 | }
116 |
117 | var isDayBaJie: Bool {
118 | get {
119 | return TaoistUtil.BA_JIE.keys.contains(lunar!.getJieQi())
120 | }
121 | }
122 |
123 | var isDayWuLa: Bool {
124 | get {
125 | return isDayIn(days: TaoistUtil.WU_LA)
126 |
127 | }
128 | }
129 |
130 | var isDayBaHui: Bool {
131 | get {
132 | return TaoistUtil.BA_HUI.keys.contains(lunar!.getDayInGanZhi())
133 | }
134 | }
135 |
136 | var isDayMingWu:Bool {
137 | get {
138 | return "戊" == lunar!.getDayGan()
139 | }
140 | }
141 |
142 | var isDayAnWu: Bool {
143 | get {
144 | return lunar!.getDayZhi() == TaoistUtil.AN_WU[abs(month) - 1]
145 | }
146 | }
147 |
148 | var isDayWu: Bool {
149 | get {
150 | return isDayMingWu || isDayAnWu
151 | }
152 | }
153 |
154 | var isDayTianShe: Bool {
155 | get {
156 | var ret: Bool = false;
157 | let monthRoot: String = lunar!.getMonthZhi()
158 | let dayColumn: String = lunar!.getDayInGanZhi();
159 | if ("寅卯辰".contains(monthRoot)) {
160 | if ("戊寅" == dayColumn) {
161 | ret = true;
162 | }
163 | } else if ("巳午未".contains(monthRoot)) {
164 | if ("甲午" == dayColumn) {
165 | ret = true;
166 | }
167 | } else if ("申酉戌".contains(monthRoot)) {
168 | if ("戊申" == dayColumn) {
169 | ret = true;
170 | }
171 | } else if ("亥子丑".contains(monthRoot)) {
172 | if ("甲子" == dayColumn) {
173 | ret = true;
174 | }
175 | }
176 | return ret;
177 | }
178 | }
179 |
180 | func toString() -> String {
181 | return "\(yearInChinese)年\(monthInChinese)月\(dayInChinese)";
182 | }
183 |
184 | func toFullString() -> String {
185 | return "道歷\(yearInChinese)年,天運\(lunar!.getYearInGanZhi())年,\(lunar!.getMonthInGanZhi())月,\(lunar!.getDayInGanZhi())日。\(monthInChinese)月\(dayInChinese)日,\(lunar!.getTimeZhi())時。"
186 | }
187 | }
188 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/TaoistFestival.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | /// 道历节日
8 | struct TaoistFestival {
9 | /// 名称
10 | var name: String
11 |
12 | /// 备注
13 | var remark: String
14 |
15 | init(name: String, remark: String = "") {
16 | self.name = name;
17 | self.remark = remark
18 | }
19 |
20 | func toString() -> String {
21 | return name
22 | }
23 |
24 | func toFullString() -> String {
25 | var s: String = name
26 | if (remark.count > 0) {
27 | s += "["
28 | s += remark
29 | s += "]"
30 | }
31 | return s
32 | }
33 | }
34 |
35 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Timeset.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Timeset.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/14.
6 | //
7 | // Timeset
8 | import Foundation
9 |
10 | @available(watchOS 8.0, *)
11 | @available(iOS 15.0, *)
12 | @available(macOS 12.0, *)
13 | public struct Timeset {
14 | /// 月支,按正月起寅排列
15 | static let MONTH_ZHI: [String] = [
16 | "",
17 | "寅",
18 | "卯",
19 | "辰",
20 | "巳",
21 | "午",
22 | "未",
23 | "申",
24 | "酉",
25 | "戌",
26 | "亥",
27 | "子",
28 | "丑"
29 | ]
30 |
31 | /// 长生十二神
32 | static let CHANG_SHENG: [String] = [
33 | "长生",
34 | "沐浴",
35 | "冠带",
36 | "临官",
37 | "帝旺",
38 | "衰",
39 | "病",
40 | "死",
41 | "墓",
42 | "绝",
43 | "胎",
44 | "养"
45 | ]
46 |
47 | /// 长生十二神日干偏移值,五阳干顺推,五阴干逆推
48 | static let CHANG_SHENG_OFFSET: [String: Int] = [
49 | "甲": 1,
50 | "丙": 10,
51 | "戊": 10,
52 | "庚": 7,
53 | "壬": 4,
54 | "乙": 6,
55 | "丁": 9,
56 | "己": 9,
57 | "辛": 0,
58 | "癸": 3
59 | ]
60 |
61 | /// 流派,2晚子时日柱按当天,1晚子时日柱按明天
62 | public var genre: Int = 1
63 |
64 | /// 阴历
65 | public var lunar: Lunar;
66 |
67 | public init(lunar: Lunar) {
68 | self.lunar = lunar
69 | }
70 |
71 | public init(lunar: Lunar, genre: Int) {
72 | self.lunar = lunar
73 | self.genre = genre
74 | }
75 |
76 | // int getSect() => _sect;
77 |
78 | // void setSect(int sect) {
79 | // _sect = (1 == sect) ? 1 : 2;
80 | // }
81 |
82 | public func getLunar() -> Lunar {
83 | return lunar
84 | }
85 |
86 | public func getYear() -> String {
87 | return lunar.getYearInGanZhiExact()
88 | }
89 |
90 | public func getYearGan() -> String {
91 | return lunar.getYearGanExact()
92 | }
93 |
94 | public func getYearZhi() -> String {
95 | return lunar.getYearZhiExact()
96 | }
97 |
98 | public func getYearHideGan() -> [String] {
99 | return LunarUtil.ZHI_HIDE_GAN[getYearZhi()]!
100 | }
101 |
102 | public func getYearWuXing() -> String {
103 | return "\(LunarUtil.WU_XING_GAN[getYearGan()]!)\(LunarUtil.WU_XING_ZHI[getYearZhi()]!)"
104 | }
105 |
106 | public func getYearNaYin() -> String {
107 | return LunarUtil.NAYIN[getYear()]!
108 | }
109 |
110 | public func getYearShiShenGan(isShort: Bool = false) -> String {
111 | if (isShort) {
112 | return LunarUtil.SHI_SHEN_GAN_SHORT["\(getDayGan())\(getYearGan())"]!
113 | }
114 | return LunarUtil.SHI_SHEN_GAN["\(getDayGan())\(getYearGan())"]!
115 | }
116 |
117 | public func getShiShenZhi(zhi: String, isShort: Bool) -> [String] {
118 | let hideGan: [String] = LunarUtil.ZHI_HIDE_GAN[zhi]!;
119 | var l: [String] = [];
120 | for gan in hideGan {
121 | if (isShort) {
122 | l.append(LunarUtil.SHI_SHEN_ZHI_SHORT["\(getDayGan())\(zhi)\(gan)"]!)
123 | } else {
124 | l.append(LunarUtil.SHI_SHEN_ZHI["\(getDayGan())\(zhi)\(gan)"]!)
125 | }
126 | }
127 | return l;
128 | }
129 |
130 | public func getShiShenGan(stem: String, isShort: Bool) -> String {
131 | if (isShort) {
132 | return LunarUtil.SHI_SHEN_GAN_SHORT["\(getDayGan())\(stem)"]!
133 | }
134 | return LunarUtil.SHI_SHEN_GAN["\(getDayGan())\(stem)"]!
135 | }
136 |
137 | public func getYearShiShenZhi(isShort: Bool = false) -> [String] {
138 | return getShiShenZhi(zhi: getYearZhi(), isShort: isShort)
139 | }
140 |
141 | func getDayGanIndex() -> Int {
142 | return genre == 2 ? lunar.getDayGanIndexExact2() : lunar.getDayGanIndexExact()
143 | }
144 |
145 | func getDayZhiIndex() -> Int {
146 | return genre == 2 ? lunar.getDayZhiIndexExact2() : lunar.getDayZhiIndexExact()
147 | }
148 |
149 | public func getDiShi(zhiIndex: Int) -> String {
150 | let offset: Int? = Timeset.CHANG_SHENG_OFFSET[getDayGan()]
151 | var index: Int = offset! + (getDayGanIndex() % 2 == 0 ? zhiIndex : -zhiIndex)
152 | if (index >= 12) {
153 | index -= 12
154 | }
155 | if (index < 0) {
156 | index += 12
157 | }
158 | return Timeset.CHANG_SHENG[index];
159 | }
160 |
161 | public func getYearDiShi() -> String {
162 | return getDiShi(zhiIndex: lunar.getYearZhiIndexExact())
163 | }
164 |
165 | public func getMonth() -> String {
166 | return lunar.getMonthInGanZhiExact()
167 | }
168 |
169 | public func getMonthGan() -> String {
170 | return lunar.getMonthGanExact()
171 | }
172 |
173 | public func getMonthZhi() -> String {
174 | return lunar.getMonthZhiExact()
175 | }
176 |
177 | public func getMonthHideGan() -> [String] {
178 | return LunarUtil.ZHI_HIDE_GAN[getMonthZhi()]!
179 | }
180 |
181 | public func getMonthWuXing() -> String {
182 | return "\(LunarUtil.WU_XING_GAN[getMonthGan()]!)\(LunarUtil.WU_XING_ZHI[getMonthZhi()]!)"
183 | }
184 |
185 | public func getMonthNaYin() -> String {
186 | return LunarUtil.NAYIN[getMonth()]!
187 | }
188 |
189 | public func getMonthShiShenGan(isShort: Bool = false) -> String {
190 | if (isShort) {
191 | return LunarUtil.SHI_SHEN_GAN_SHORT["\(getDayGan())\(getMonthGan())"]!
192 | }
193 | return LunarUtil.SHI_SHEN_GAN["\(getDayGan())\(getMonthGan())"]!
194 | }
195 |
196 | public func getMonthShiShenZhi(isShort: Bool = false) -> [String] {
197 | return getShiShenZhi(zhi: getMonthZhi(), isShort: isShort)
198 | }
199 |
200 | public func getMonthDiShi() -> String {
201 | return getDiShi(zhiIndex: lunar.getMonthZhiIndexExact())
202 | }
203 |
204 | public func getDay() -> String {
205 | return genre == 2 ? lunar.getDayInGanZhiExact2() : lunar.getDayInGanZhiExact()
206 | }
207 |
208 | public func getDayGan() -> String {
209 | return genre == 2 ? lunar.getDayGanExact2() : lunar.getDayGanExact()
210 | }
211 |
212 | public func getDayZhi() -> String {
213 | return genre == 2 ? lunar.getDayZhiExact2() : lunar.getDayZhiExact()
214 | }
215 |
216 | public func getDayHideGan() -> [String] {
217 | return LunarUtil.ZHI_HIDE_GAN[getDayZhi()]!
218 | }
219 |
220 | public func getDayWuXing() -> String {
221 | return "\(LunarUtil.WU_XING_GAN[getDayGan()]!)\(LunarUtil.WU_XING_ZHI[getDayZhi()]!)"
222 | }
223 |
224 | public func getDayNaYin() -> String {
225 | return LunarUtil.NAYIN[getDay()]!
226 | }
227 |
228 | public func getDayShiShenGan() -> String {
229 | return "日元"
230 | }
231 |
232 | public func getDayShiShenZhi(isShort: Bool = false) -> [String] {
233 | return getShiShenZhi(zhi: getDayZhi(), isShort: isShort)
234 | }
235 |
236 | public func getDayDiShi() -> String {
237 | return getDiShi(zhiIndex: getDayZhiIndex())
238 | }
239 |
240 | public func getTime() -> String {
241 | return lunar.getTimeInGanZhi()
242 | }
243 |
244 | public func getTimeGan() -> String {
245 | return lunar.getTimeGan()
246 | }
247 |
248 | public func getTimeZhi() -> String {
249 | return lunar.getTimeZhi()
250 | }
251 |
252 | public func getTimeHideGan() -> [String] {
253 | return LunarUtil.ZHI_HIDE_GAN[getTimeZhi()]!
254 | }
255 |
256 | public func getTimeWuXing() -> String {
257 | return "\(LunarUtil.WU_XING_GAN[getTimeGan()]!)\(LunarUtil.WU_XING_ZHI[getTimeZhi()]!)"
258 | }
259 |
260 | public func getTimeNaYin() -> String {
261 | return LunarUtil.NAYIN[getTime()]!
262 | }
263 |
264 | public func getTimeShiShenGan(isShort: Bool = false) -> String {
265 | if (isShort) {
266 | return LunarUtil.SHI_SHEN_GAN_SHORT["\(getDayGan())\(getTimeGan())"]!
267 | }
268 | return LunarUtil.SHI_SHEN_GAN["\(getDayGan())\(getTimeGan())"]!
269 | }
270 |
271 | public func getTimeShiShenZhi(isShort: Bool = false) -> [String] {
272 | getShiShenZhi(zhi: getTimeZhi(), isShort: isShort)
273 | }
274 |
275 | public func getTimeDiShi() -> String {
276 | getDiShi(zhiIndex: lunar.getTimeZhiIndex())
277 | }
278 |
279 | public func getTaiYuan() -> String {
280 | var ganIndex: Int = lunar.getMonthGanIndexExact() + 1;
281 | if (ganIndex >= 10) {
282 | ganIndex -= 10;
283 | }
284 | var zhiIndex: Int = lunar.getMonthZhiIndexExact() + 3;
285 | if (zhiIndex >= 12) {
286 | zhiIndex -= 12;
287 | }
288 | return "\(LunarUtil.GAN[ganIndex + 1])\(LunarUtil.ZHI[zhiIndex + 1])"
289 | }
290 |
291 | func getTaiYuanNaYin() -> String {
292 | return LunarUtil.NAYIN[getTaiYuan()]!
293 | }
294 |
295 | public func getTaiXi() -> String {
296 | let ganIndex: Int = (genre == 2) ? lunar.getDayGanIndexExact2() : lunar.getDayGanIndexExact();
297 | let zhiIndex: Int = (genre == 2) ? lunar.getDayZhiIndexExact2() : lunar.getDayZhiIndexExact();
298 |
299 | return "\(LunarUtil.HE_GAN_5[ganIndex])\(LunarUtil.HE_ZHI_6[zhiIndex])"
300 | }
301 |
302 | public func getTaiXiNaYin() -> String {
303 | return LunarUtil.NAYIN[getTaiXi()]!
304 | }
305 |
306 | func getMingGong() -> String {
307 | var monthZhiIndex: Int = 0
308 | var timeZhiIndex: Int = 0
309 | for i in 0.. 12) {
320 | zhiIndex -= 12;
321 | }
322 |
323 | var jiaZiIndex: Int = LunarUtil.getJiaZiIndex(ganZhi: lunar.getMonthInGanZhiExact()) - (monthZhiIndex - zhiIndex);
324 | if (jiaZiIndex >= 60) {
325 | jiaZiIndex -= 60;
326 | }
327 | if (jiaZiIndex < 0) {
328 | jiaZiIndex += 60;
329 | }
330 | return LunarUtil.JIA_ZI[jiaZiIndex];
331 | }
332 |
333 | public func getMingGongNaYin() -> String {
334 | return LunarUtil.NAYIN[getMingGong()]!
335 | }
336 |
337 | public func getShenGong() -> String {
338 | var monthZhiIndex: Int = 0;
339 | var timeZhiIndex: Int = 0;
340 | for i in 0.. 12) {
351 | zhiIndex -= 12;
352 | }
353 | var jiaZiIndex: Int = LunarUtil.getJiaZiIndex(ganZhi: lunar.getMonthInGanZhiExact()) - (monthZhiIndex - zhiIndex)
354 | if (jiaZiIndex >= 60) {
355 | jiaZiIndex -= 60;
356 | }
357 | if (jiaZiIndex < 0) {
358 | jiaZiIndex += 60;
359 | }
360 | return LunarUtil.JIA_ZI[jiaZiIndex];
361 | }
362 |
363 | public func getShenGongNaYin() -> String {
364 | return LunarUtil.NAYIN[getShenGong()]!
365 | }
366 |
367 | public func getYun(gender: Int, genre: Int = 1) -> Yun {
368 | return Yun(lunar: lunar, gender: gender, genre: genre)
369 | }
370 |
371 | public func getYearXun() -> String {
372 | return lunar.getYearXunExact()
373 | }
374 |
375 | public func getYearXunKong() -> String {
376 | return lunar.getYearXunKongExact()
377 | }
378 |
379 | public func getMonthXun() -> String {
380 | return lunar.getMonthXunExact()
381 | }
382 |
383 | public func getMonthXunKong() -> String {
384 | return lunar.getMonthXunKongExact()
385 | }
386 |
387 | public func getDayXun() -> String {
388 | return genre == 2 ? lunar.getDayXunExact2() : lunar.getDayXunExact()
389 | }
390 |
391 | public func getDayXunKong() -> String {
392 | return genre == 2 ? lunar.getDayXunKongExact2() : lunar.getDayXunKongExact()
393 | }
394 |
395 | public func getTimeXun() -> String {
396 | return lunar.getTimeXun()
397 | }
398 |
399 | public func getTimeXunKong() -> String {
400 | return lunar.getTimeXunKong()
401 | }
402 |
403 | func toString() -> String {
404 | return "\(getYear()) \(getMonth()) \(getDay()) \(getTime())"
405 | }
406 | }
407 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Timeset/DaYun.swift:
--------------------------------------------------------------------------------
1 | //
2 | // DaYun.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 | // Episode
8 |
9 | @available(watchOS 8.0, *)
10 | @available(iOS 15.0, *)
11 | @available(macOS 12.0, *)
12 | public struct DaYun: Hashable {
13 | /// 开始年(含)
14 | public var startYear: Int = 0
15 |
16 | /// 结束年(含)
17 | public var endYear: Int = 0
18 |
19 | /// 开始年龄(含)
20 | public var startAge: Int = 0
21 |
22 | /// 结束年龄(含)
23 | public var endAge: Int = 0
24 |
25 | /// 序数,0-9
26 | public var index: Int = 0 {
27 | didSet {
28 | calcProperties(yun: yun!, index: index)
29 | }
30 | }
31 |
32 | /// 运
33 | public var yun: Yun? {
34 | didSet {
35 | calcProperties(yun: yun!, index: index)
36 | }
37 | }
38 |
39 | /// 阴历
40 | public var lunar: Lunar?
41 |
42 | public init(yun: Yun, index: Int) {
43 | self.yun = yun
44 | self.index = index
45 | calcProperties(yun: yun, index: index)
46 | }
47 |
48 | mutating func calcProperties(yun: Yun, index: Int) {
49 | // _yun = yun;
50 | self.lunar = yun.lunar
51 | // _index = index;
52 | let birthYear: Int = lunar!.getSolar().year;
53 | let year: Int = yun.getStartSolar().year;
54 | if (index < 1) {
55 | startYear = birthYear;
56 | startAge = 1;
57 | endYear = year - 1;
58 | endAge = year - birthYear;
59 | } else {
60 | let add: Int = (index - 1) * 10;
61 | startYear = year + add;
62 | startAge = startYear - birthYear + 1;
63 | endYear = startYear + 9;
64 | endAge = startAge + 9;
65 | }
66 | }
67 |
68 | // int getStartYear() => _startYear;
69 | //
70 | // int getEndYear() => _endYear;
71 | //
72 | // int getStartAge() => _startAge;
73 | //
74 | // int getEndAge() => _endAge;
75 | //
76 | // int getIndex() => _index;
77 | //
78 | // Lunar getLunar() => _lunar!;
79 |
80 | public func getGanZhi() -> String {
81 | if (index < 1) {
82 | return ""
83 | }
84 | var offset: Int = LunarUtil.getJiaZiIndex(ganZhi: lunar!.getMonthInGanZhiExact());
85 | offset += yun!.isGoWith ? index : -index;
86 | let size: Int = LunarUtil.JIA_ZI.count;
87 | if (offset >= size) {
88 | offset -= size
89 | }
90 | if (offset < 0) {
91 | offset += size
92 | }
93 | return LunarUtil.JIA_ZI[offset];
94 | }
95 |
96 | public func getGan() -> String {
97 | let characters = Array(getGanZhi())
98 | return String(characters[0])
99 | }
100 |
101 | public func getZhi() -> String {
102 | let characters = Array(getGanZhi())
103 | return String(characters[1])
104 | }
105 |
106 | public func getXun() -> String {
107 | return LunarUtil.getXun(ganZhi: getGanZhi())
108 | }
109 |
110 | public func getXunKong() -> String {
111 | return LunarUtil.getXunKong(ganZhi: getGanZhi())
112 | }
113 |
114 | /// 获取10轮流年
115 | public func getLiuNian() -> [LiuNian] {
116 | return getLiuNianBy(n: 10)
117 | }
118 |
119 | /// 获取流年
120 | /// [n] 轮数
121 | public func getLiuNianBy(n: Int) -> [LiuNian] {
122 | var num: Int = n
123 | if (index < 1) {
124 | num = endYear - startYear + 1
125 | }
126 | var l: [LiuNian] = [];
127 | for i in 0.. [XiaoYun] {
135 | return getXiaoYunBy(n: 10);
136 | }
137 |
138 | /// 获取小运
139 | /// [n] 轮数
140 | public func getXiaoYunBy(n: Int) -> [XiaoYun] {
141 | var num: Int = n
142 | if (index < 1) {
143 | num = endYear - startYear + 1;
144 | }
145 | var l: [XiaoYun] = [];
146 | for i in 0.. String {
47 | return LunarUtil.MONTH[index + 1]
48 | }
49 |
50 | // int getIndex() => _index;
51 | //
52 | // int getYear() => _year;
53 | //
54 | // int getAge() => _age;
55 |
56 | public func getGanZhi() -> String {
57 | // 干支与出生日期和起运日期都没关系
58 | var offset: Int = LunarUtil.getJiaZiIndex(ganZhi: lunar!.getJieQiTable()["立春"]!.getLunar().getYearInGanZhiExact()) + index;
59 | if (daYun!.index > 0) {
60 | offset += daYun!.startAge - 1;
61 | }
62 | offset %= LunarUtil.JIA_ZI.count;
63 | return LunarUtil.JIA_ZI[offset];
64 | }
65 |
66 | public func getGan() -> String {
67 | let characters = Array(getGanZhi())
68 | return String(characters[0])
69 | }
70 |
71 | public func getZhi() -> String {
72 | let characters = Array(getGanZhi())
73 | return String(characters[1])
74 | }
75 |
76 | public func getXun() -> String {
77 | return LunarUtil.getXun(ganZhi: getGanZhi())
78 | }
79 |
80 | public func getXunKong() -> String {
81 | return LunarUtil.getXunKong(ganZhi: getGanZhi())
82 | }
83 |
84 | public func getLiuYue() -> [LiuYue] {
85 | let n: Int = 12
86 | var l: [LiuYue] = []
87 | for i in 0.. String {
19 | return LunarUtil.MONTH[index + 1]
20 | }
21 |
22 | public func getGanZhi() -> String {
23 | let gan: String = getGan()
24 | let zhi: String = getZhi()
25 | return gan + zhi;
26 | }
27 |
28 | public func getGan() -> String {
29 | var offset: Int = 0;
30 | let yearGan: String = String(liuNian.getGanZhi().prefix(1));
31 | if ("甲" == yearGan || "己" == yearGan) {
32 | offset = 2
33 | } else if ("乙" == yearGan || "庚" == yearGan) {
34 | offset = 4
35 | } else if ("丙" == yearGan || "辛" == yearGan) {
36 | offset = 6
37 | } else if ("丁" == yearGan || "壬" == yearGan) {
38 | offset = 8
39 | }
40 | let gan: String = LunarUtil.GAN[(index + offset) % 10 + 1];
41 | return gan;
42 | }
43 |
44 | public func getZhi() -> String {
45 | let zhi: String = LunarUtil.ZHI[(index + LunarUtil.BASE_MONTH_ZHI_INDEX) % 12 + 1];
46 | return zhi;
47 | }
48 |
49 | public func getXun() -> String {
50 | return LunarUtil.getXun(ganZhi: getGanZhi())
51 | }
52 |
53 | public func getXunKong() -> String {
54 | return LunarUtil.getXunKong(ganZhi: getGanZhi())
55 | }
56 | }
57 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Timeset/XiaoYun.swift:
--------------------------------------------------------------------------------
1 | //
2 | // XiaoYun.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 | // 小运
8 | @available(watchOS 8.0, *)
9 | @available(iOS 15.0, *)
10 | @available(macOS 12.0, *)
11 | public struct XiaoYun {
12 | /// 序数,0-9
13 | public var index: Int = 0 {
14 | didSet {
15 | year = daYun!.startYear + index
16 | age = daYun!.startAge + index
17 | }
18 | }
19 |
20 | /// 年
21 | public var year: Int = 0
22 |
23 | /// 年龄
24 | public var age: Int = 0
25 |
26 | /// 是否顺推
27 | var isGoWith: Bool = false
28 |
29 | /// 大运
30 | public var daYun: DaYun? {
31 | didSet {
32 | lunar = daYun!.lunar
33 | year = daYun!.startYear + index
34 | age = daYun!.startAge + index
35 | }
36 | }
37 |
38 | /// 阴历
39 | public var lunar: Lunar?
40 |
41 | public init(daYun: DaYun, index: Int, isGoWith: Bool) {
42 | self.daYun = daYun
43 | self.index = index
44 | self.isGoWith = isGoWith
45 | self.year = daYun.startYear + index
46 | self.age = daYun.startAge + index
47 | self.lunar = daYun.lunar
48 | }
49 |
50 | // XiaoYun(DaYun daYun, int index, bool forward) {
51 | // _daYun = daYun;
52 | // _lunar = daYun.getLunar();
53 | // _index = index;
54 | // _year = daYun.getStartYear() + index;
55 | // _age = daYun.getStartAge() + index;
56 | // _forward = forward;
57 | // }
58 | //
59 | // int getIndex() => _index;
60 | //
61 | // int getYear() => _year;
62 | //
63 | // int getAge() => _age;
64 |
65 | public func getGanZhi() -> String {
66 | var offset: Int = LunarUtil.getJiaZiIndex(ganZhi: lunar!.getTimeInGanZhi());
67 | var add: Int = index + 1;
68 | if (daYun!.index > 0) {
69 | add += daYun!.startAge - 1;
70 | }
71 | offset += isGoWith ? add : -add;
72 | let size: Int = LunarUtil.JIA_ZI.count;
73 | while (offset < 0) {
74 | offset += size;
75 | }
76 | offset %= size;
77 | return LunarUtil.JIA_ZI[offset];
78 | }
79 |
80 | public func getGan() -> String {
81 | let characters = Array(getGanZhi())
82 | return String(characters[0])
83 | }
84 |
85 | public func getZhi() -> String {
86 | let characters = Array(getGanZhi())
87 | return String(characters[1])
88 | }
89 |
90 | public func getXun() -> String {
91 | return LunarUtil.getXun(ganZhi: getGanZhi())
92 | }
93 |
94 | public func getXunKong() -> String {
95 | return LunarUtil.getXunKong(ganZhi: getGanZhi())
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Timeset/Yun.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Yun.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 | // 运
8 |
9 | import Foundation
10 |
11 | @available(watchOS 8.0, *)
12 | @available(iOS 15.0, *)
13 | @available(macOS 12.0, *)
14 | public struct Yun: Hashable {
15 | // 性别(1男,0女)
16 | public var gender: Int = 0
17 |
18 | // 起运年数
19 | public var startYear: Int = 0
20 |
21 | // 起运月数
22 | public var startMonth: Int = 0
23 |
24 | // 起运天数
25 | public var startDay: Int = 0
26 |
27 | // 起运小时数
28 | public var startHour: Int = 0
29 |
30 | // 是否顺推
31 | public var isGoWith: Bool = false
32 |
33 | public var genre: Int = 1
34 |
35 | // 阴历
36 | public var lunar: Lunar? {
37 | didSet {
38 | let yang = 0 == (lunar?.getYearGanIndexExact())! % 2
39 | let man = 1 == gender
40 | isGoWith = (yang && man) || (!yang && !man)
41 | computeStart(genre: genre)
42 | }
43 | }
44 |
45 | public init(lunar: Lunar, gender: Int, genre: Int = 1) {
46 | self.lunar = lunar
47 | self.gender = gender
48 | // 阳
49 | let yang: Bool = 0 == lunar.getYearGanIndexExact() % 2
50 | // 男
51 | let man: Bool = 1 == gender
52 | isGoWith = (yang && man) || (!yang && !man)
53 | computeStart(genre: genre)
54 | }
55 |
56 | mutating func computeStart(genre: Int) {
57 | // 上节
58 | let prev: JieQi = lunar!.getPrevJie()
59 | // 下节
60 | let next: JieQi = lunar!.getNextJie()
61 | // 出生日期
62 | let current: Solar = lunar!.solar!
63 | // 阳男阴女顺推,阴男阳女逆推
64 | let start: Solar = isGoWith ? current : prev.solar!
65 | let end: Solar = isGoWith ? next.solar! : current
66 |
67 | var year: Int
68 | var month: Int
69 | var day: Int
70 | var hour: Int = 0
71 |
72 | if (2 == genre) {
73 | var minutes: Int = Calendar(identifier: .gregorian).dateComponents([.minute], from: start.calendar, to: end.calendar).minute!
74 | year = Int(floor(Double(minutes) / 4320))
75 | minutes -= year * 4320
76 | month = Int(floor(Double(minutes) / 360))
77 | minutes -= month * 360
78 | day = Int(floor(Double(minutes) / 12))
79 | minutes -= day * 12
80 | hour = minutes * 2
81 | } else {
82 | let endTimeZhiIndex: Int = (end.hour == 23)
83 | ? 11
84 | : LunarUtil.getTimeZhiIndex(hm: end.toHm())
85 | let startTimeZhiIndex: Int = (start.hour == 23)
86 | ? 11
87 | : LunarUtil.getTimeZhiIndex(hm: start.toHm())
88 | // 时辰差
89 | var hourDiff: Int = endTimeZhiIndex - startTimeZhiIndex
90 | // 天数差
91 | var dayDiff: Int = ExactDate.getDaysBetween(ay: start.year, am: start.month,
92 | ad: start.day, by: end.year, bm: end.month, bd: end.day)
93 | if (hourDiff < 0) {
94 | hourDiff += 12
95 | dayDiff -= 1
96 | }
97 | let monthDiff: Int = Int(floor(Double(hourDiff) * 10 / 30))
98 | month = dayDiff * 4 + monthDiff
99 | day = hourDiff * 10 - monthDiff * 30
100 | year = Int(floor(Double(month) / 12))
101 | month = month - year * 12
102 | }
103 | startYear = year
104 | startMonth = month
105 | startDay = day
106 | startHour = hour
107 | }
108 |
109 | // int getGender() => _gender
110 | //
111 | // int getStartYear() => _startYear
112 | //
113 | // int getStartMonth() => _startMonth
114 | //
115 | // int getStartDay() => _startDay
116 | //
117 | // int getStartHour() => _startHour
118 | //
119 | // bool isForward() => _forward
120 |
121 | // Lunar getLunar() => _lunar!
122 |
123 | public func getStartSolar() -> Solar {
124 | let birth: Solar = lunar!.solar!
125 | var year: Int = birth.year + startYear
126 | var month: Int = birth.month + startMonth
127 | if (month > 12) {
128 | month -= 12
129 | year += 1
130 | }
131 | var day: Int = birth.day + startDay
132 | var hour: Int = birth.hour + startHour
133 | if (hour > 24) {
134 | day += 1
135 | hour -= 24
136 | }
137 | let days: Int = SolarUtil.getDaysOfMonth(year: year, month: month)
138 | if (day > days) {
139 | day -= days
140 | month += 1
141 | if (month > 12) {
142 | month -= 12
143 | year += 1
144 | }
145 | }
146 | return Solar(fromYmdHms: year, month: month, day: day, hour: hour, minute: birth.minute, second: birth.second)
147 | }
148 |
149 | /// 获取10轮大运
150 | public func getDaYun() -> [DaYun]{
151 | return getDaYunBy(n: 10)
152 | }
153 |
154 | /// 获取大运
155 | /// [n] 轮数
156 | public func getDaYunBy(n: Int) -> [DaYun]{
157 | var l: [DaYun] = []
158 | for i in 0.. String {
407 | return XIU_27[(XIU_OFFSET[abs(month) - 1] + day - 1) % XIU_27.count]
408 | }
409 | }
410 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Utils/SolarUtil.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarUtil.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/11.
6 | //
7 |
8 | import Foundation
9 |
10 | struct SolarUtil {
11 |
12 | static let WEEK: [String] = ["日", "一", "二", "三", "四", "五", "六"]
13 |
14 | static let DAYS_OF_MONTH: [Int] = [
15 | 31,
16 | 28,
17 | 31,
18 | 30,
19 | 31,
20 | 30,
21 | 31,
22 | 31,
23 | 30,
24 | 31,
25 | 30,
26 | 31
27 | ]
28 |
29 | static let XING_ZUO: [String] = [
30 | "白羊",
31 | "金牛",
32 | "双子",
33 | "巨蟹",
34 | "狮子",
35 | "处女",
36 | "天秤",
37 | "天蝎",
38 | "射手",
39 | "摩羯",
40 | "水瓶",
41 | "双鱼"
42 | ]
43 |
44 | /// 日期对应的节日
45 | static let FESTIVAL: [String: String] = [
46 | "1-1": "元旦节",
47 | "2-14": "情人节",
48 | "3-8": "妇女节",
49 | "3-12": "植树节",
50 | "3-15": "消费者权益日",
51 | "4-1": "愚人节",
52 | "5-1": "劳动节",
53 | "5-4": "青年节",
54 | "6-1": "儿童节",
55 | "7-1": "建党节",
56 | "8-1": "建军节",
57 | "9-10": "教师节",
58 | "10-1": "国庆节",
59 | "10-31": "万圣节前夜",
60 | "11-1": "万圣节",
61 | "12-24": "平安夜",
62 | "12-25": "圣诞节"
63 | ]
64 |
65 | /// 几月第几个星期几对应的节日
66 | static let WEEK_FESTIVAL: [String: String] = [
67 | "3-0-1": "全国中小学生安全教育日",
68 | "5-2-0": "母亲节",
69 | "6-3-0": "父亲节",
70 | "11-4-4": "感恩节"
71 | ]
72 |
73 | /// 日期对应的非正式节日
74 | static let OTHER_FESTIVAL: [String: [String]] = [
75 | "1-8": ["周恩来逝世纪念日"],
76 | "1-10": ["中国人民警察节", "中国公安110宣传日"],
77 | "1-21": ["列宁逝世纪念日"],
78 | "1-26": ["国际海关日"],
79 | "2-2": ["世界湿地日"],
80 | "2-4": ["世界抗癌日"],
81 | "2-7": ["京汉铁路罢工纪念"],
82 | "2-10": ["国际气象节"],
83 | "2-19": ["邓小平逝世纪念日"],
84 | "2-21": ["国际母语日"],
85 | "2-24": ["第三世界青年日"],
86 | "3-1": ["国际海豹日"],
87 | "3-3": ["全国爱耳日"],
88 | "3-5": ["周恩来诞辰纪念日", "中国青年志愿者服务日"],
89 | "3-6": ["世界青光眼日"],
90 | "3-12": ["孙中山逝世纪念日"],
91 | "3-14": ["马克思逝世纪念日"],
92 | "3-17": ["国际航海日"],
93 | "3-18": ["全国科技人才活动日"],
94 | "3-21": ["世界森林日", "世界睡眠日"],
95 | "3-22": ["世界水日"],
96 | "3-23": ["世界气象日"],
97 | "3-24": ["世界防治结核病日"],
98 | "4-2": ["国际儿童图书日"],
99 | "4-7": ["世界卫生日"],
100 | "4-22": ["列宁诞辰纪念日"],
101 | "4-23": ["世界图书和版权日"],
102 | "4-26": ["世界知识产权日"],
103 | "5-3": ["世界新闻自由日"],
104 | "5-5": ["马克思诞辰纪念日"],
105 | "5-8": ["世界红十字日"],
106 | "5-11": ["世界肥胖日"],
107 | "5-25": ["525心理健康节"],
108 | "5-27": ["上海解放日"],
109 | "5-31": ["世界无烟日"],
110 | "6-5": ["世界环境日"],
111 | "6-6": ["全国爱眼日"],
112 | "6-8": ["世界海洋日"],
113 | "6-11": ["中国人口日"],
114 | "6-14": ["世界献血日"],
115 | "7-1": ["香港回归纪念日"],
116 | "7-7": ["中国人民抗日战争纪念日"],
117 | "7-11": ["世界人口日"],
118 | "8-5": ["恩格斯逝世纪念日"],
119 | "8-6": ["国际电影节"],
120 | "8-12": ["国际青年日"],
121 | "8-22": ["邓小平诞辰纪念日"],
122 | "9-3": ["中国抗日战争胜利纪念日"],
123 | "9-8": ["世界扫盲日"],
124 | "9-9": ["毛泽东逝世纪念日"],
125 | "9-14": ["世界清洁地球日"],
126 | "9-18": ["九一八事变纪念日"],
127 | "9-20": ["全国爱牙日"],
128 | "9-21": ["国际和平日"],
129 | "9-27": ["世界旅游日"],
130 | "10-4": ["世界动物日"],
131 | "10-10": ["辛亥革命纪念日"],
132 | "10-13": ["中国少年先锋队诞辰日"],
133 | "10-25": ["抗美援朝纪念日"],
134 | "11-12": ["孙中山诞辰纪念日"],
135 | "11-17": ["国际大学生节"],
136 | "11-28": ["恩格斯诞辰纪念日"],
137 | "12-1": ["世界艾滋病日"],
138 | "12-12": ["西安事变纪念日"],
139 | "12-13": ["国家公祭日"],
140 | "12-26": ["毛泽东诞辰纪念日"],
141 | ]
142 |
143 | /// 是否闰年
144 | /// @param year 年
145 | /// @return true/false 闰年/非闰年
146 | static func isLeapYear(year: Int)->Bool {
147 | return (year % 4 == 0 && year % 100 != 0) || (year % 400 == 0)
148 | }
149 |
150 | /// 获取某年某月有多少天
151 | ///
152 | /// @param year 年
153 | /// @param month 月
154 | /// @return 天数
155 | static func getDaysOfMonth(year: Int, month: Int)->Int {
156 | if (1582 == year && 10 == month) {
157 | return 21;
158 | }
159 | let m: Int = month - 1
160 | var d: Int = DAYS_OF_MONTH[m];
161 | //公历闰年2月多一天
162 | if (m == 1 && isLeapYear(year: year)) {
163 | d += 1
164 | }
165 | return d
166 | }
167 |
168 | /// 获取某年有多少天(平年365天,闰年366天)
169 | ///
170 | /// @param year 年
171 | /// @return 天数
172 | static func getDaysOfYear(year: Int) -> Int {
173 | return isLeapYear(year: year) ? 366 : 365
174 | }
175 |
176 | /// 获取某天为当年的第几天
177 | ///
178 | /// @param year 年
179 | /// @param month 月
180 | /// @param day 日
181 | /// @return 第几天
182 | static func getDaysInYear(year: Int, month: Int, day: Int) -> Int {
183 | var days: Int = 0;
184 | for i in 1..= 15) {
189 | days -= 10;
190 | }
191 | return days;
192 | }
193 |
194 | /// 获取某年某月有多少周
195 | ///
196 | /// @param year 年
197 | /// @param month 月
198 | /// @param start 星期几作为一周的开始,1234560分别代表星期一至星期天
199 | /// @return 周数
200 | static func getWeeksOfMonth(year: Int, month: Int, start: Int) -> Int {
201 | let days: Int = getDaysOfMonth(year: year, month: month)
202 | var week: Int = Calendar(identifier: .gregorian).component(.weekday, from: ExactDate.fromYmd(year: year, month: month, day: Int(1))) - 1
203 | if (week == -1) {
204 | week = 0;
205 | }
206 | return Int(ceil(Double(days + week - start) * 1.0 / Double(WEEK.count)))
207 | }
208 | }
209 |
--------------------------------------------------------------------------------
/Sources/SwiftLunar/Utils/TaoistUtil.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaoistUtil.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | // Taoist tools
8 | struct TaoistUtil {
9 | /// 八会日
10 | static let BA_HUI: [String: String] = [
11 | "丙午": "天会",
12 | "壬午": "地会",
13 | "壬子": "人会",
14 | "庚午": "日会",
15 | "庚申": "月会",
16 | "辛酉": "星辰会",
17 | "甲辰": "五行会",
18 | "甲戌": "四时会"
19 | ]
20 |
21 | /// 八节日
22 | static let BA_JIE: [String: String] = [
23 | "立春": "东北方度仙上圣天尊同梵炁始青天君下降",
24 | "春分": "东方玉宝星上天尊同青帝九炁天君下降",
25 | "立夏": "东南方好生度命天尊同梵炁始丹天君下降",
26 | "夏至": "南方玄真万福天尊同赤帝三炁天君下降",
27 | "立秋": "西南方太灵虚皇天尊同梵炁始素天君下降",
28 | "秋分": "西方太妙至极天尊同白帝七炁天君下降",
29 | "立冬": "西北方无量太华天尊同梵炁始玄天君下降",
30 | "冬至": "北方玄上玉宸天尊同黑帝五炁天君下降"
31 | ]
32 |
33 | /// 三会日
34 | static let SAN_HUI: [String] = ["1-7", "7-7", "10-15"];
35 |
36 | /// 三元日
37 | static let SAN_YUAN: [String] = ["1-15", "7-15", "10-15"];
38 |
39 | /// 五腊日
40 | static let WU_LA: [String] = ["1-1", "5-5", "7-7", "10-1", "12-8"];
41 |
42 | /// 暗戊
43 | static let AN_WU: [String] = [
44 | "未",
45 | "戌",
46 | "辰",
47 | "寅",
48 | "午",
49 | "子",
50 | "酉",
51 | "申",
52 | "巳",
53 | "亥",
54 | "卯",
55 | "丑"
56 | ]
57 |
58 | // The festivals of Taoist
59 | static let FESTIVAL: [String: [TaoistFestival]] = [
60 | "1-1": [TaoistFestival(name: "天腊之辰", remark: "天腊,此日五帝会于东方九炁青天")],
61 | "1-3": [TaoistFestival(name: "郝真人圣诞"), TaoistFestival(name: "孙真人圣诞")],
62 | "1-5": [TaoistFestival(name: "孙祖清静元君诞")],
63 | "1-7": [TaoistFestival(name: "举迁赏会", remark: "此日上元赐福,天官同地水二官考校罪福")],
64 | "1-9": [TaoistFestival(name: "玉皇上帝圣诞")],
65 | "1-13": [TaoistFestival(name: "关圣帝君飞升")],
66 | "1-15": [TaoistFestival(name: "上元天官圣诞"), TaoistFestival(name: "老祖天师圣诞")],
67 | "1-19": [TaoistFestival(name: "长春邱真人(邱处机)圣诞")],
68 | "1-28": [TaoistFestival(name: "许真君(许逊天师)圣诞")],
69 | "2-1": [TaoistFestival(name: "勾陈天皇大帝圣诞"), TaoistFestival(name: "长春刘真人(刘渊然)圣诞")],
70 | "2-2": [TaoistFestival(name: "土地正神诞"), TaoistFestival(name: "姜太公圣诞")],
71 | "2-3": [TaoistFestival(name: "文昌梓潼帝君圣诞")],
72 | "2-6": [TaoistFestival(name: "东华帝君圣诞")],
73 | "2-13": [TaoistFestival(name: "度人无量葛真君圣诞")],
74 | "2-15": [TaoistFestival(name: "太清道德天尊(太上老君)圣诞")],
75 | "2-19": [TaoistFestival(name: "慈航真人圣诞")],
76 | "3-1": [TaoistFestival(name: "谭祖(谭处端)长真真人圣诞")],
77 | "3-3": [TaoistFestival(name: "玄天上帝圣诞")],
78 | "3-6": [TaoistFestival(name: "眼光娘娘圣诞")],
79 | "3-15": [TaoistFestival(name: "天师张大真人圣诞"), TaoistFestival(name: "财神赵公元帅圣诞")],
80 | "3-16": [TaoistFestival(name: "三茅真君得道之辰"), TaoistFestival(name: "中岳大帝圣诞")],
81 | "3-18": [TaoistFestival(name: "王祖(王处一)玉阳真人圣诞"), TaoistFestival(name: "后土娘娘圣诞")],
82 | "3-19": [TaoistFestival(name: "太阳星君圣诞")],
83 | "3-20": [TaoistFestival(name: "子孙娘娘圣诞")],
84 | "3-23": [TaoistFestival(name: "天后妈祖圣诞")],
85 | "3-26": [TaoistFestival(name: "鬼谷先师诞")],
86 | "3-28": [TaoistFestival(name: "东岳大帝圣诞")],
87 | "4-1": [TaoistFestival(name: "长生谭真君成道之辰")],
88 | "4-10": [TaoistFestival(name: "何仙姑圣诞")],
89 | "4-14": [TaoistFestival(name: "吕祖纯阳祖师圣诞")],
90 | "4-15": [TaoistFestival(name: "钟离祖师圣诞")],
91 | "4-18": [
92 | TaoistFestival(name: "北极紫微大帝圣诞"),
93 | TaoistFestival(name: "泰山圣母碧霞元君诞"),
94 | TaoistFestival(name: "华佗神医先师诞")
95 | ],
96 | "4-20": [TaoistFestival(name: "眼光圣母娘娘诞")],
97 | "4-28": [TaoistFestival(name: "神农先帝诞")],
98 | "5-1": [TaoistFestival(name: "南极长生大帝圣诞")],
99 | "5-5": [
100 | TaoistFestival(name: "地腊之辰", remark: "地腊,此日五帝会于南方三炁丹天"),
101 | TaoistFestival(name: "南方雷祖圣诞"),
102 | TaoistFestival(name: "地祗温元帅圣诞"),
103 | TaoistFestival(name: "雷霆邓天君圣诞")
104 | ],
105 | "5-11": [TaoistFestival(name: "城隍爷圣诞")],
106 | "5-13": [TaoistFestival(name: "关圣帝君降神"), TaoistFestival(name: "关平太子圣诞")],
107 | "5-18": [TaoistFestival(name: "张天师圣诞")],
108 | "5-20": [TaoistFestival(name: "马祖丹阳真人圣诞")],
109 | "5-29": [TaoistFestival(name: "紫青白祖师圣诞")],
110 | "6-1": [TaoistFestival(name: "南斗星君下降")],
111 | "6-2": [TaoistFestival(name: "南斗星君下降")],
112 | "6-3": [TaoistFestival(name: "南斗星君下降")],
113 | "6-4": [TaoistFestival(name: "南斗星君下降")],
114 | "6-5": [TaoistFestival(name: "南斗星君下降")],
115 | "6-6": [TaoistFestival(name: "南斗星君下降")],
116 | "6-10": [TaoistFestival(name: "刘海蟾祖师圣诞")],
117 | "6-15": [TaoistFestival(name: "灵官王天君圣诞")],
118 | "6-19": [TaoistFestival(name: "慈航(观音)成道日")],
119 | "6-23": [TaoistFestival(name: "火神圣诞")],
120 | "6-24": [TaoistFestival(name: "南极大帝中方雷祖圣诞"), TaoistFestival(name: "关圣帝君圣诞")],
121 | "6-26": [TaoistFestival(name: "二郎真君圣诞")],
122 | "7-7": [
123 | TaoistFestival(name: "道德腊之辰", remark: "道德腊,此日五帝会于西方七炁素天"),
124 | TaoistFestival(name: "庆生中会", remark: "此日中元赦罪,地官同天水二官考校罪福")
125 | ],
126 | "7-12": [TaoistFestival(name: "西方雷祖圣诞")],
127 | "7-15": [TaoistFestival(name: "中元地官大帝圣诞")],
128 | "7-18": [TaoistFestival(name: "王母娘娘圣诞")],
129 | "7-20": [TaoistFestival(name: "刘祖(刘处玄)长生真人圣诞")],
130 | "7-22": [TaoistFestival(name: "财帛星君文财神增福相公李诡祖圣诞")],
131 | "7-26": [TaoistFestival(name: "张三丰祖师圣诞")],
132 | "8-1": [TaoistFestival(name: "许真君飞升日")],
133 | "8-3": [TaoistFestival(name: "九天司命灶君诞")],
134 | "8-5": [TaoistFestival(name: "北方雷祖圣诞")],
135 | "8-10": [TaoistFestival(name: "北岳大帝诞辰")],
136 | "8-15": [TaoistFestival(name: "太阴星君诞")],
137 | "9-1": [TaoistFestival(name: "北斗九皇降世之辰")],
138 | "9-2": [TaoistFestival(name: "北斗九皇降世之辰")],
139 | "9-3": [TaoistFestival(name: "北斗九皇降世之辰")],
140 | "9-4": [TaoistFestival(name: "北斗九皇降世之辰")],
141 | "9-5": [TaoistFestival(name: "北斗九皇降世之辰")],
142 | "9-6": [TaoistFestival(name: "北斗九皇降世之辰")],
143 | "9-7": [TaoistFestival(name: "北斗九皇降世之辰")],
144 | "9-8": [TaoistFestival(name: "北斗九皇降世之辰")],
145 | "9-9": [
146 | TaoistFestival(name: "北斗九皇降世之辰"),
147 | TaoistFestival(name: "斗姥元君圣诞"),
148 | TaoistFestival(name: "重阳帝君圣诞"),
149 | TaoistFestival(name: "玄天上帝飞升"),
150 | TaoistFestival(name: "酆都大帝圣诞")
151 | ],
152 | "9-22": [TaoistFestival(name: "增福财神诞")],
153 | "9-23": [TaoistFestival(name: "萨翁真君圣诞")],
154 | "9-28": [TaoistFestival(name: "五显灵官马元帅圣诞")],
155 | "10-1": [
156 | TaoistFestival(name: "民岁腊之辰", remark: "民岁腊,此日五帝会于北方五炁黑天"),
157 | TaoistFestival(name: "东皇大帝圣诞")
158 | ],
159 | "10-3": [TaoistFestival(name: "三茅应化真君圣诞")],
160 | "10-6": [TaoistFestival(name: "天曹诸司五岳五帝圣诞")],
161 | "10-15": [
162 | TaoistFestival(name: "下元水官大帝圣诞"),
163 | TaoistFestival(name: "建生大会", remark: "此日下元解厄,水官同天地二官考校罪福")
164 | ],
165 | "10-18": [TaoistFestival(name: "地母娘娘圣诞")],
166 | "10-19": [TaoistFestival(name: "长春邱真君飞升")],
167 | "10-20": [TaoistFestival(name: "虚靖天师(即三十代天师弘悟张真人)诞")],
168 | "11-6": [TaoistFestival(name: "西岳大帝圣诞")],
169 | "11-9": [TaoistFestival(name: "湘子韩祖圣诞")],
170 | "11-11": [TaoistFestival(name: "太乙救苦天尊圣诞")],
171 | "11-26": [TaoistFestival(name: "北方五道圣诞")],
172 | "12-8": [TaoistFestival(name: "王侯腊之辰", remark: "王侯腊,此日五帝会于上方玄都玉京")],
173 | "12-16": [TaoistFestival(name: "南岳大帝圣诞"), TaoistFestival(name: "福德正神诞")],
174 | "12-20": [TaoistFestival(name: "鲁班先师圣诞")],
175 | "12-21": [TaoistFestival(name: "天猷上帝圣诞")],
176 | "12-22": [TaoistFestival(name: "重阳祖师圣诞")],
177 | "12-23": [TaoistFestival(name: "祭灶王", remark: "最适宜谢旧年太岁,开启拜新年太岁")],
178 | "12-25": [TaoistFestival(name: "玉帝巡天"), TaoistFestival(name: "天神下降")],
179 | "12-29": [TaoistFestival(name: "清静孙真君(孙不二)成道")]
180 | ]
181 | }
182 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/BrassMonkeysTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BrassMonkeysTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class SBrassMonkeysTests: XCTestCase {
12 | func testBrassMonkeys1() throws {
13 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 21)
14 | let lunar: Lunar = solar.getLunar()
15 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
16 | XCTAssertEqual(brassMonkeys!.toString(), "一九")
17 | XCTAssertEqual(brassMonkeys!.toFullString(), "一九第1天")
18 | }
19 |
20 | func testBrassMonkeys2() throws {
21 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 22)
22 | let lunar: Lunar = solar.getLunar()
23 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
24 | XCTAssertEqual(brassMonkeys!.toString(), "一九")
25 | XCTAssertEqual(brassMonkeys!.toFullString(), "一九第2天")
26 | }
27 |
28 | func testBrassMonkeys3() throws {
29 | let solar: Solar = Solar(fromYmd: 2020, month: 1, day: 7)
30 | let lunar: Lunar = solar.getLunar()
31 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
32 | XCTAssertEqual(brassMonkeys!.toString(), "二九")
33 | XCTAssertEqual(brassMonkeys!.toFullString(), "二九第8天")
34 | }
35 |
36 | func testBrassMonkeys4() throws {
37 | let solar: Solar = Solar(fromYmd: 2021, month: 1, day: 6)
38 | let lunar: Lunar = solar.getLunar()
39 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
40 | XCTAssertEqual(brassMonkeys!.toString(), "二九")
41 | XCTAssertEqual(brassMonkeys!.toFullString(), "二九第8天")
42 | }
43 |
44 | func testBrassMonkeys5() throws {
45 | let solar: Solar = Solar(fromYmd: 2021, month: 1, day: 8)
46 | let lunar: Lunar = solar.getLunar()
47 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
48 | XCTAssertEqual(brassMonkeys!.toString(), "三九")
49 | XCTAssertEqual(brassMonkeys!.toFullString(), "三九第1天")
50 | }
51 |
52 | func testBrassMonkeys6() throws {
53 | let solar: Solar = Solar(fromYmd: 2021, month: 3, day: 5)
54 | let lunar: Lunar = solar.getLunar()
55 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
56 | XCTAssertEqual(brassMonkeys!.toString(), "九九")
57 | XCTAssertEqual(brassMonkeys!.toFullString(), "九九第3天")
58 | }
59 |
60 | func testBrassMonkeys7() throws {
61 | let solar: Solar = Solar(fromYmd: 2021, month: 7, day: 5)
62 | let lunar: Lunar = solar.getLunar()
63 | let brassMonkeys: BrassMonkeys? = lunar.getBrassMonkeys()
64 | XCTAssertNil(brassMonkeys)
65 | }
66 | }
67 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/BuddhisTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BuddhisTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/21.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class BuddhisTests: XCTestCase {
12 | func testBuddhis1() throws {
13 | let buddhis: Buddhis = Buddhis(lunar: Lunar(fromYmdHms: 2021, lunarMonth: 10, lunarDay: 14))
14 | XCTAssertEqual(buddhis.toFullString(), "二五六五年十月十四 (三元降) (四天王巡行)")
15 | }
16 |
17 | func testBuddhis2() throws {
18 | let buddhis: Buddhis = Buddhis(lunar: Lunar(fromYmdHms: 2020, lunarMonth: 4, lunarDay: 13))
19 | XCTAssertEqual(buddhis.xiu, "氐")
20 | XCTAssertEqual(buddhis.zheng, "土")
21 | XCTAssertEqual(buddhis.animal, "貉")
22 | XCTAssertEqual(buddhis.gong, "东")
23 | XCTAssertEqual(buddhis.shou, "青龙")
24 | }
25 | }
26 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/ConstellationTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ConstellationTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class ConstellationTests: XCTestCase {
12 |
13 | func testConstellation1() throws {
14 | let solar: Solar = Solar(fromYmd: 2020, month: 3, day: 21)
15 | XCTAssertEqual(solar.constellation, "白羊")
16 | }
17 |
18 | func testConstellation2() throws {
19 | let solar: Solar = Solar(fromYmd: 2020, month: 4, day: 19)
20 | XCTAssertEqual(solar.constellation, "白羊")
21 | }
22 |
23 | func testConstellation3() throws {
24 | let solar: Solar = Solar(fromYmd: 2020, month: 4, day: 20)
25 | XCTAssertEqual(solar.constellation, "金牛")
26 | }
27 |
28 | func testConstellation4() throws {
29 | let solar: Solar = Solar(fromYmd: 2020, month: 5, day: 20)
30 | XCTAssertEqual(solar.constellation, "金牛")
31 | }
32 |
33 | func testConstellation5() throws {
34 | let solar: Solar = Solar(fromYmd: 2020, month: 5, day: 21)
35 | XCTAssertEqual(solar.constellation, "双子")
36 | }
37 |
38 | func testConstellation6() throws {
39 | let solar: Solar = Solar(fromYmd: 2020, month: 6, day: 21)
40 | XCTAssertEqual(solar.constellation, "双子")
41 | }
42 |
43 | func testConstellation7() throws {
44 | let solar: Solar = Solar(fromYmd: 2020, month: 6, day: 22)
45 | XCTAssertEqual(solar.constellation, "巨蟹")
46 | }
47 |
48 | func testConstellation8() throws {
49 | let solar: Solar = Solar(fromYmd: 2020, month: 7, day: 22)
50 | XCTAssertEqual(solar.constellation, "巨蟹")
51 | }
52 |
53 | func testConstellation9() throws {
54 | let solar: Solar = Solar(fromYmd: 2020, month: 7, day: 23)
55 | XCTAssertEqual(solar.constellation, "狮子")
56 | }
57 |
58 | func testConstellation10() throws {
59 | let solar: Solar = Solar(fromYmd: 2020, month: 8, day: 22)
60 | XCTAssertEqual(solar.constellation, "狮子")
61 | }
62 |
63 | func testConstellation11() throws {
64 | let solar: Solar = Solar(fromYmd: 2020, month: 8, day: 23)
65 | XCTAssertEqual(solar.constellation, "处女")
66 | }
67 |
68 | func testConstellation12() throws {
69 | let solar: Solar = Solar(fromYmd: 2020, month: 9, day: 22)
70 | XCTAssertEqual(solar.constellation, "处女")
71 | }
72 |
73 | func testConstellation13() throws {
74 | let solar: Solar = Solar(fromYmd: 2020, month: 9, day: 23)
75 | XCTAssertEqual(solar.constellation, "天秤")
76 | }
77 |
78 | func testConstellation14() throws {
79 | let solar: Solar = Solar(fromYmd: 2020, month: 10, day: 23)
80 | XCTAssertEqual(solar.constellation, "天秤")
81 | }
82 |
83 | func testConstellation15() throws {
84 | let solar: Solar = Solar(fromYmd: 2020, month: 10, day: 24)
85 | XCTAssertEqual(solar.constellation, "天蝎")
86 | }
87 |
88 | func testConstellation16() throws {
89 | let solar: Solar = Solar(fromYmd: 2020, month: 11, day: 22)
90 | XCTAssertEqual(solar.constellation, "天蝎")
91 | }
92 |
93 | func testConstellation17() throws {
94 | let solar: Solar = Solar(fromYmd: 2020, month: 11, day: 23)
95 | XCTAssertEqual(solar.constellation, "射手")
96 | }
97 |
98 | func testConstellation18() throws {
99 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 21)
100 | XCTAssertEqual(solar.constellation, "射手")
101 | }
102 |
103 | func testConstellation19() throws {
104 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 22)
105 | XCTAssertEqual(solar.constellation, "摩羯")
106 | }
107 |
108 | func testConstellation20() throws {
109 | let solar: Solar = Solar(fromYmd: 2021, month: 1, day: 19)
110 | XCTAssertEqual(solar.constellation, "摩羯")
111 | }
112 |
113 | func testConstellation21() throws {
114 | let solar: Solar = Solar(fromYmd: 2021, month: 1, day: 20)
115 | XCTAssertEqual(solar.constellation, "水瓶")
116 | }
117 |
118 | func testConstellation22() throws {
119 | let solar: Solar = Solar(fromYmd: 2021, month: 2, day: 18)
120 | XCTAssertEqual(solar.constellation, "水瓶")
121 | }
122 |
123 | func testConstellation23() throws {
124 | let solar: Solar = Solar(fromYmd: 2021, month: 2, day: 19)
125 | XCTAssertEqual(solar.constellation, "双鱼")
126 | }
127 |
128 | func testConstellation24() throws {
129 | let solar: Solar = Solar(fromYmd: 2021, month: 3, day: 20)
130 | XCTAssertEqual(solar.constellation, "双鱼")
131 | }
132 | }
133 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/CycleVoid.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CycleVoid.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class CycleVoidTests: XCTestCase {
12 | func testCycleVoid1() throws {
13 | let solar: Solar = Solar(fromYmdHms: 2020, month: 11, day: 19, hour: 0, minute: 0, second: 0)
14 | let lunar: Lunar = solar.getLunar()
15 | XCTAssertEqual(lunar.getYearXun(), "甲午")
16 | }
17 |
18 | func testCycleVoid2() throws {
19 | let solar: Solar = Solar(fromYmdHms: 2020, month: 11, day: 19, hour: 0, minute: 0, second: 0)
20 | let lunar: Lunar = solar.getLunar()
21 | XCTAssertEqual(lunar.getYearXunKong(), "辰巳")
22 | XCTAssertEqual(lunar.getMonthXunKong(), "午未")
23 | XCTAssertEqual(lunar.getDayXunKong(), "戌亥")
24 | }
25 |
26 | func testCycleVoid3() throws {
27 | let solar: Solar = Solar(fromYmdHms: 1990, month: 12, day: 23, hour: 8, minute: 37, second: 0)
28 | let lunar: Lunar = solar.getLunar()
29 | let timeset: Timeset = lunar.getTimeset()
30 | XCTAssertEqual(timeset.getDayXunKong(), "子丑")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/DateTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Date_test.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/13.
6 | //
7 | import XCTest
8 |
9 | @available(macOS 12.0, *)
10 | final class DateTests: XCTestCase {
11 | func testDate() throws {
12 | let dateFormatter = DateFormatter()
13 | dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss.SSS"
14 | let date: Date = dateFormatter.date(from: "0320-02-03 08:00:00.000")!
15 | XCTAssertEqual(date.formatted(.dateTime.year()), "320")
16 | }
17 |
18 | }
19 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/DogDaysTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // File.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/21.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class DogDaysTests: XCTestCase {
12 | func testDogDays1() throws {
13 | let solar: Solar = Solar(fromYmd: 2011, month: 7, day: 14)
14 | let lunar: Lunar = solar.getLunar()
15 | let dogDays: DogDays? = lunar.getDogDays()
16 | XCTAssertEqual(dogDays!.toString(), "初伏")
17 | XCTAssertEqual(dogDays!.toFullString(), "初伏第1天")
18 | }
19 |
20 | func testDogDays2() throws {
21 | let solar: Solar = Solar(fromYmd: 2011, month: 7, day: 23)
22 | let lunar: Lunar = solar.getLunar()
23 | let dogDays: DogDays? = lunar.getDogDays()
24 | XCTAssertEqual(dogDays!.toString(), "初伏")
25 | XCTAssertEqual(dogDays!.toFullString(), "初伏第10天")
26 | }
27 |
28 | func testDogDays3() throws {
29 | let solar: Solar = Solar(fromYmd: 2011, month: 7, day: 24)
30 | let lunar: Lunar = solar.getLunar()
31 | let dogDays: DogDays? = lunar.getDogDays()
32 | XCTAssertEqual(dogDays!.toString(), "中伏")
33 | XCTAssertEqual(dogDays!.toFullString(), "中伏第1天")
34 | }
35 |
36 | func testDogDays4() throws {
37 | let solar: Solar = Solar(fromYmd: 2011, month: 8, day: 12)
38 | let lunar: Lunar = solar.getLunar()
39 | let dogDays: DogDays? = lunar.getDogDays()
40 | XCTAssertEqual(dogDays!.toString(), "中伏")
41 | XCTAssertEqual(dogDays!.toFullString(), "中伏第20天")
42 | }
43 |
44 | func testDogDays5() throws {
45 | let solar: Solar = Solar(fromYmd: 2011, month: 8, day: 13)
46 | let lunar: Lunar = solar.getLunar()
47 | let dogDays: DogDays? = lunar.getDogDays()
48 | XCTAssertEqual(dogDays!.toString(), "末伏")
49 | XCTAssertEqual(dogDays!.toFullString(), "末伏第1天")
50 | }
51 |
52 | func testDogDays6() throws {
53 | let solar: Solar = Solar(fromYmd: 2011, month: 8, day: 22)
54 | let lunar: Lunar = solar.getLunar()
55 | let dogDays: DogDays? = lunar.getDogDays()
56 | XCTAssertEqual(dogDays!.toString(), "末伏")
57 | XCTAssertEqual(dogDays!.toFullString(), "末伏第10天")
58 | }
59 |
60 | func testDogDays7() throws {
61 | let solar: Solar = Solar(fromYmd: 2011, month: 7, day: 13)
62 | let lunar: Lunar = solar.getLunar()
63 | let dogDays: DogDays? = lunar.getDogDays()
64 | XCTAssertNil(dogDays)
65 | }
66 |
67 | func testDogDays8() throws {
68 | let solar: Solar = Solar(fromYmd: 2011, month: 8, day: 23)
69 | let lunar: Lunar = solar.getLunar()
70 | let dogDays: DogDays? = lunar.getDogDays()
71 | XCTAssertNil(dogDays)
72 | }
73 |
74 | func testDogDays9() throws {
75 | let solar: Solar = Solar(fromYmd: 2012, month: 7, day: 18)
76 | let lunar: Lunar = solar.getLunar()
77 | let dogDays: DogDays? = lunar.getDogDays()
78 | XCTAssertEqual(dogDays!.toString(), "初伏")
79 | XCTAssertEqual(dogDays!.toFullString(), "初伏第1天")
80 | }
81 |
82 | func testDogDays10() throws {
83 | let solar: Solar = Solar(fromYmd: 2012, month: 8, day: 5)
84 | let lunar: Lunar = solar.getLunar()
85 | let dogDays: DogDays? = lunar.getDogDays()
86 | XCTAssertEqual(dogDays!.toString(), "中伏")
87 | XCTAssertEqual(dogDays!.toFullString(), "中伏第9天")
88 | }
89 |
90 | func testDogDays11() throws {
91 | let solar: Solar = Solar(fromYmd: 2012, month: 8, day: 8)
92 | let lunar: Lunar = solar.getLunar()
93 | let dogDays: DogDays? = lunar.getDogDays()
94 | XCTAssertEqual(dogDays!.toString(), "末伏")
95 | XCTAssertEqual(dogDays!.toFullString(), "末伏第2天")
96 | }
97 |
98 | func testDogDays12() throws {
99 | let solar: Solar = Solar(fromYmd: 2020, month: 7, day: 17)
100 | let lunar: Lunar = solar.getLunar()
101 | let dogDays: DogDays? = lunar.getDogDays()
102 | XCTAssertEqual(dogDays!.toString(), "初伏")
103 | XCTAssertEqual(dogDays!.toFullString(), "初伏第2天")
104 | }
105 |
106 | func testDogDays13() throws {
107 | let solar: Solar = Solar(fromYmd: 2020, month: 7, day: 26)
108 | let lunar: Lunar = solar.getLunar()
109 | let dogDays: DogDays? = lunar.getDogDays()
110 | XCTAssertEqual(dogDays!.toString(), "中伏")
111 | XCTAssertEqual(dogDays!.toFullString(), "中伏第1天")
112 | }
113 |
114 | func testDogDays14() throws {
115 | let solar: Solar = Solar(fromYmd: 2020, month: 8, day: 24)
116 | let lunar: Lunar = solar.getLunar()
117 | let dogDays: DogDays? = lunar.getDogDays()
118 | XCTAssertEqual(dogDays!.toString(), "末伏")
119 | XCTAssertEqual(dogDays!.toFullString(), "末伏第10天")
120 | }
121 | }
122 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/FestivalTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Festival_test.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/18.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class FestivalTests: XCTestCase {
13 | func testFestival() throws {
14 | let solar1: Solar = Solar(fromYmd: 2020, month: 11, day: 26)
15 | XCTAssertEqual(solar1.festivals.description, "[\"感恩节\"]")
16 |
17 | let solar2: Solar = Solar(fromYmd: 2020, month: 6, day: 21)
18 | XCTAssertEqual(solar2.festivals.description, "[\"父亲节\"]")
19 |
20 | let solar3: Solar = Solar(fromYmd: 2021, month: 5, day: 9)
21 | XCTAssertEqual(solar3.festivals.description, "[\"母亲节\"]")
22 |
23 | let solar4: Solar = Solar(fromYmd: 1986, month: 11, day: 27)
24 | XCTAssertEqual(solar4.festivals.description, "[\"感恩节\"]")
25 |
26 | let solar5: Solar = Solar(fromYmd: 1985, month: 6, day: 16)
27 | XCTAssertEqual(solar5.festivals.description, "[\"父亲节\"]")
28 |
29 | let solar6: Solar = Solar(fromYmd: 1984, month: 5, day: 13)
30 | XCTAssertEqual(solar6.festivals.description, "[\"母亲节\"]")
31 |
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/HalfYearTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // HalfYearTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/19.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class HalfYearTests: XCTestCase {
13 | func testHalfYearForFirst() throws {
14 |
15 | let halfYear: SolarHalfYear = SolarHalfYear(year: 2019, month: 5)
16 | XCTAssertEqual(halfYear.toString(), "2019.1")
17 | XCTAssertEqual(halfYear.toFullString(), "2019年上半年")
18 | }
19 |
20 | func testHalfYearForSecond() throws {
21 |
22 | let halfYear: SolarHalfYear = SolarHalfYear(year: 2019, month: 5).next(halfYears: 1)
23 | XCTAssertEqual(halfYear.toString(), "2019.2")
24 | XCTAssertEqual(halfYear.toFullString(), "2019年下半年")
25 | }
26 |
27 | func testHalfYearForThird() throws {
28 |
29 | let halfYear: SolarHalfYear = SolarHalfYear(year: 2019, month: 5).next(halfYears: -1)
30 | XCTAssertEqual(halfYear.toString(), "2018.2")
31 | XCTAssertEqual(halfYear.toFullString(), "2018年下半年")
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/HolidayTestst.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Holiday_test.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/18.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class HolidayTests: XCTestCase {
13 | @available(macOS 13.0, *)
14 | func testHoliday() throws {
15 | let holiday: Holiday? = HolidayUtil.getHoliday(ymd: "2010-01-01")
16 | // let solar1: Solar = Solar(fromYmd: 2020, month: 11, day: 26)
17 | XCTAssertEqual(holiday!.name, "元旦节")
18 |
19 | // HolidayUtil.fix
20 | }
21 | }
22 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/JulianDayTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // JulianDayTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/18.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class JulianDayTests: XCTestCase {
13 | func testJulianDay() throws {
14 | let solar11: Solar = Solar(fromYmd: 2020, month: 7, day: 15)
15 | XCTAssertEqual(solar11.julianDay, 2459045.5)
16 |
17 | let solar12: Solar = Solar(fromJulianDay: 2459045.5)
18 | XCTAssertEqual(solar12.toYmdHms(), "2020-07-15 00:00:00")
19 |
20 | let solar21: Solar = Solar(fromYmdHms: 9999, month: 12, day: 30, hour: 12, minute: 0, second: 0)
21 | XCTAssertEqual(solar21.julianDay, 5373483.0)
22 |
23 | let solar22: Solar = Solar(fromJulianDay: 5373483.0)
24 | XCTAssertEqual(solar22.toYmdHms(), "9999-12-30 12:00:00")
25 |
26 | let solar31: Solar = Solar(fromYmdHms: 1905, month: 2, day: 4, hour: 12, minute: 0, second: 0)
27 | XCTAssertEqual(solar31.julianDay, 2416881.0)
28 |
29 | let solar32: Solar = Solar(fromJulianDay: 2416881.0)
30 | XCTAssertEqual(solar32.toYmdHms(), "1905-02-04 12:00:00")
31 | }
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/LiuYaoTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LiuYaoTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class LiuYaoTests: XCTestCase {
12 | func testLiuYao1() throws {
13 | let solar: Solar = Solar(fromYmd: 2020, month: 4, day: 23)
14 | let lunar: Lunar = solar.getLunar()
15 | XCTAssertEqual(lunar.getLiuYao(), "佛灭")
16 | }
17 |
18 | func testLiuYao2() throws {
19 | let solar: Solar = Solar(fromYmd: 2021, month: 1, day: 15)
20 | let lunar: Lunar = solar.getLunar()
21 | XCTAssertEqual(lunar.getLiuYao(), "友引")
22 | }
23 |
24 | func testLiuYao3() throws {
25 | let solar: Solar = Solar(fromYmd: 2017, month: 1, day: 5)
26 | let lunar: Lunar = solar.getLunar()
27 | XCTAssertEqual(lunar.getLiuYao(), "先胜")
28 | }
29 |
30 | func testLiuYao4() throws {
31 | let solar: Solar = Solar(fromYmd: 2020, month: 4, day: 10)
32 | let lunar: Lunar = solar.getLunar()
33 | XCTAssertEqual(lunar.getLiuYao(), "友引")
34 | }
35 |
36 | func testLiuYao5() throws {
37 | let solar: Solar = Solar(fromYmd: 2020, month: 6, day: 11)
38 | let lunar: Lunar = solar.getLunar()
39 | XCTAssertEqual(lunar.getLiuYao(), "大安")
40 | }
41 |
42 | func testLiuYao6() throws {
43 | let solar: Solar = Solar(fromYmd: 2020, month: 6, day: 1)
44 | let lunar: Lunar = solar.getLunar()
45 | XCTAssertEqual(lunar.getLiuYao(), "先胜")
46 | }
47 |
48 | func testLiuYao7() throws {
49 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 8)
50 | let lunar: Lunar = solar.getLunar()
51 | XCTAssertEqual(lunar.getLiuYao(), "先负")
52 | }
53 |
54 | func testLiuYao8() throws {
55 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 11)
56 | let lunar: Lunar = solar.getLunar()
57 | XCTAssertEqual(lunar.getLiuYao(), "赤口")
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/LunarTests.swift:
--------------------------------------------------------------------------------
1 | import XCTest
2 | @testable import SwiftLunar
3 |
4 | @available(macOS 12.0, *)
5 | final class LunarTests: XCTestCase {
6 | func testLunar() throws {
7 | let lunar: Lunar = Lunar(fromYmdHms: 2019, lunarMonth: 3, lunarDay: 27, hour: 0, minute: 0, second: 0)
8 | XCTAssertEqual(lunar.toString(), "二〇一九年三月廿七")
9 | XCTAssertEqual(lunar.toFullString(), "二〇一九年三月廿七 己亥(猪)年 戊辰(龙)月 戊戌(狗)日 子(鼠)时 纳音[平地木 大林木 平地木 桑柘木] 星期三 西方白虎 星宿[参水猿](吉) 彭祖百忌[戊不受田田主不祥 戌不吃犬作怪上床] 喜神方位[巽](东南) 阳贵神方位[艮](东北) 阴贵神方位[坤](西南) 福神方位[艮](东北) 财神方位[坎](正北) 冲[(壬辰)龙] 煞[北]")
10 | XCTAssertEqual(lunar.solar?.toString(), "2019-05-01")
11 | XCTAssertEqual(lunar.solar?.toFullString(), "2019-05-01 00:00:00 星期三 (劳动节) 金牛座")
12 | }
13 | func testLunar1() throws {
14 | let solar: Solar = Solar(fromYmdHms: 1, month: 1, day: 1, hour: 12, minute: 0, second: 0)
15 | XCTAssertEqual(solar.getLunar().toString(), "〇年冬月十八")
16 | }
17 | func testLunar2() throws {
18 | let solar: Solar = Solar(fromYmdHms: 9999, month: 12, day: 31, hour: 12, minute: 0, second: 0)
19 | XCTAssertEqual(solar.getLunar().toString(), "九九九九年腊月初二")
20 | }
21 | func testLunar3() throws {
22 | let lunar: Lunar = Lunar(fromYmdHms: 0, lunarMonth: 11, lunarDay: 18, hour: 12, minute: 0, second: 0)
23 | XCTAssertEqual(lunar.solar!.toString(), "0001-01-01")
24 | }
25 | func testLunar4() throws {
26 | let lunar: Lunar = Lunar(fromYmdHms: 9999, lunarMonth: 12, lunarDay: 2, hour: 12, minute: 0, second: 0)
27 | XCTAssertEqual(lunar.solar!.toString(), "9999-12-31")
28 | }
29 | func testLunar5() throws {
30 | let lunar: Lunar = Lunar(fromYmdHms: 1905, lunarMonth: 1, lunarDay: 1, hour: 12, minute: 0, second: 0)
31 | XCTAssertEqual(lunar.solar!.toString(), "1905-02-04")
32 | }
33 | func testLunar6() throws {
34 | let lunar: Lunar = Lunar(fromYmdHms: 2038, lunarMonth: 12, lunarDay: 29, hour: 12, minute: 0, second: 0)
35 | XCTAssertEqual(lunar.solar!.toString(), "2039-01-23")
36 | }
37 | func testLunar7() throws {
38 | let lunar: Lunar = Lunar(fromYmdHms: 2020, lunarMonth: -4, lunarDay: 2, hour: 13, minute: 0, second: 0)
39 | XCTAssertEqual(lunar.toString(), "二〇二〇年闰四月初二")
40 | XCTAssertEqual(lunar.solar!.toString(), "2020-05-24")
41 | }
42 | func testLunar8() throws {
43 | let lunar: Lunar = Lunar(fromYmdHms: 2020, lunarMonth: 12, lunarDay: 10, hour: 13, minute: 0, second: 0)
44 | XCTAssertEqual(lunar.toString(), "二〇二〇年腊月初十")
45 | XCTAssertEqual(lunar.solar!.toString(), "2021-01-22")
46 | }
47 | func testLunar9() throws {
48 | let lunar: Lunar = Lunar(fromYmdHms: 1500, lunarMonth: 1, lunarDay: 1, hour: 12, minute: 0, second: 0)
49 | XCTAssertEqual(lunar.solar!.toString(), "1500-01-31")
50 | }
51 | func testLunar10() throws {
52 | let lunar: Lunar = Lunar(fromYmdHms: 1500, lunarMonth: 12, lunarDay: 29, hour: 12, minute: 0, second: 0)
53 | XCTAssertEqual(lunar.solar!.toString(), "1501-01-18")
54 | }
55 | func testLunar11() throws {
56 | let solar: Solar = Solar(fromYmdHms: 1500, month: 1, day: 1, hour: 12, minute: 0, second: 0)
57 | XCTAssertEqual(solar.getLunar().toString(), "一四九九年腊月初一")
58 | }
59 | func testLunar12() throws {
60 | let solar: Solar = Solar(fromYmdHms: 1500, month: 12, day: 31, hour: 12, minute: 0, second: 0)
61 | XCTAssertEqual(solar.getLunar().toString(), "一五〇〇年腊月十一")
62 | }
63 | func testLunar13() throws {
64 | let solar: Solar = Solar(fromYmdHms: 1582, month: 10, day: 4, hour: 12, minute: 0, second: 0)
65 | XCTAssertEqual(solar.getLunar().toString(), "一五八二年九月十八")
66 | }
67 | func testLunar14() throws {
68 | let solar: Solar = Solar(fromYmdHms: 1582, month: 10, day: 15, hour: 12, minute: 0, second: 0)
69 | XCTAssertEqual(solar.getLunar().toString(), "一五八二年九月十九")
70 | }
71 | func testLunar15() throws {
72 | let lunar: Lunar = Lunar(fromYmdHms: 1582, lunarMonth: 9, lunarDay: 18, hour: 12, minute: 0, second: 0)
73 | XCTAssertEqual(lunar.solar!.toString(), "1582-10-04")
74 | }
75 | func testLunar16() throws {
76 | let lunar: Lunar = Lunar(fromYmdHms: 1582, lunarMonth: 9, lunarDay: 19, hour: 12, minute: 0, second: 0)
77 | XCTAssertEqual(lunar.solar!.toString(), "1582-10-15")
78 | }
79 | func testLunar17() throws {
80 | let lunar: Lunar = Lunar(fromYmdHms: 2019, lunarMonth: 12, lunarDay: 12, hour: 11, minute: 22, second: 0)
81 | XCTAssertEqual(lunar.solar!.toString(), "2020-01-06")
82 | }
83 | func testLunar18() throws {
84 | let lunar: Lunar = Lunar(fromYmdHms: 2021, lunarMonth: 12, lunarDay: 29)
85 | XCTAssertEqual(lunar.getFestivals()[0], "除夕")
86 | }
87 | func testLunar19() throws {
88 | let lunar: Lunar = Lunar(fromYmdHms: 2020, lunarMonth: 12, lunarDay: 30)
89 | XCTAssertEqual(lunar.getFestivals()[0], "除夕")
90 | }
91 | func testLunar20() throws {
92 | let lunar: Lunar = Lunar(fromYmdHms: 2020, lunarMonth: 12, lunarDay: 29)
93 | XCTAssertEqual(lunar.getFestivals().count, 0)
94 | }
95 | func testLunar21() throws {
96 | let solar: Solar = Solar(fromYmd:2022, month:1, day:31)
97 | let lunar = solar.getLunar()
98 | XCTAssertEqual(lunar.getFestivals()[0], "除夕")
99 | }
100 | func testLunar22() throws {
101 | let lunar: Lunar = Lunar(fromYmdHms: 2033, lunarMonth: -11, lunarDay: 1)
102 | XCTAssertEqual(lunar.getSolar().toYmd(), "2033-12-22")
103 | }
104 | func testLunar23() throws {
105 | let lunar: Lunar = Lunar(fromYmdHms: 2022, lunarMonth: 1, lunarDay: 1)
106 | XCTAssertEqual(lunar.getYearNineStar().toString(), "六白金开阳")
107 | }
108 | func testLunar24() throws {
109 | let lunar: Lunar = Lunar(fromYmdHms: 2033, lunarMonth: 1, lunarDay: 1)
110 | XCTAssertEqual(lunar.getYearNineStar().toString(), "四绿木天权")
111 | }
112 | func testLunar25() throws {
113 | let solar: Solar = Solar(fromYmdHms: 2021, month: 6, day: 7, hour: 21, minute: 18, second: 0)
114 | let lunar: Lunar = solar.getLunar()
115 | XCTAssertEqual(lunar.toString(), "二〇二一年四月廿七")
116 | }
117 | func testLunar26() throws {
118 | let lunar: Lunar = Lunar(fromYmdHms: 2021, lunarMonth: 6, lunarDay: 7, hour: 21, minute: 18, second: 0)
119 | let solar: Solar = lunar.getSolar()
120 | XCTAssertEqual(solar.toString(), "2021-07-16")
121 | }
122 | func testNext() throws {
123 | let solar: Solar = Solar(fromYmdHms: 2020, month: 1, day: 10, hour: 12, minute: 0, second: 0)
124 | let lunar: Lunar = solar.getLunar()
125 | for i in -50..<50 {
126 | //To-Do Using toFullString()
127 | XCTAssertEqual(lunar.next(days: i).toString(), solar.next(days: i).getLunar().toString())
128 | }
129 | }
130 | func testLunar27() throws {
131 | let solar: Solar = Solar(fromYmd: 1989, month: 4, day: 28)
132 | let lunar: Lunar = solar.getLunar()
133 | XCTAssertEqual(lunar.day, 23)
134 | }
135 | func testLunar28() throws {
136 | let solar: Solar = Solar(fromYmd: 1990, month: 10, day: 8)
137 | let lunar: Lunar = solar.getLunar()
138 | XCTAssertEqual(lunar.getMonthInGanZhiExact(), "乙酉")
139 | }
140 | func testLunar29() throws {
141 | let solar: Solar = Solar(fromYmd: 1990, month: 10, day: 9)
142 | let lunar: Lunar = solar.getLunar()
143 | XCTAssertEqual(lunar.getMonthInGanZhiExact(), "丙戌")
144 | }
145 | func testLunar30() throws {
146 | let solar: Solar = Solar(fromYmd: 1990, month: 10, day: 8)
147 | let lunar: Lunar = solar.getLunar()
148 | XCTAssertEqual(lunar.getMonthInGanZhi(), "丙戌")
149 | }
150 | func testLunar31() throws {
151 | let solar: Solar = Solar(fromYmdHms: 1987, month: 4, day: 17, hour: 9, minute: 0, second: 0)
152 | let lunar: Lunar = solar.getLunar()
153 | XCTAssertEqual(lunar.toString(), "一九八七年三月二十")
154 | XCTAssertEqual(lunar.getSolar().toYmdHms(), "1987-04-17 09:00:00")
155 | }
156 | func testLunar32() throws {
157 | let lunar: Lunar = Lunar(fromYmdHms: 2034, lunarMonth: 1, lunarDay: 1)
158 | XCTAssertEqual(lunar.getSolar().toYmd(), "2034-02-19")
159 | }
160 | func testLunar33() throws {
161 | let lunar: Lunar = Lunar(fromYmdHms: 2033, lunarMonth: 12, lunarDay: 1)
162 | XCTAssertEqual(lunar.getSolar().toYmd(), "2034-01-20")
163 | }
164 | func testLunar34() throws {
165 | let lunar: Lunar = Lunar(fromYmdHms: 37, lunarMonth: -12, lunarDay: 1)
166 | XCTAssertEqual(lunar.getMonthInChinese(), "闰腊")
167 | }
168 | func testLunar35() throws {
169 | var lunar: Lunar = Lunar(fromYmdHms: 56, lunarMonth: -12, lunarDay: 1)
170 | XCTAssertEqual(lunar.getMonthInChinese(), "闰腊")
171 |
172 | lunar = Lunar(fromYmdHms: 75, lunarMonth: -11, lunarDay: 1)
173 | XCTAssertEqual(lunar.getMonthInChinese(), "闰冬")
174 |
175 | lunar = Lunar(fromYmdHms: 94, lunarMonth: -11, lunarDay: 1)
176 | XCTAssertEqual(lunar.getMonthInChinese(), "闰冬")
177 |
178 | lunar = Lunar(fromYmdHms: 94, lunarMonth: 12, lunarDay: 1)
179 | XCTAssertEqual(lunar.getMonthInChinese(), "腊")
180 |
181 | lunar = Lunar(fromYmdHms: 113, lunarMonth: 12, lunarDay: 1)
182 | XCTAssertEqual(lunar.getMonthInChinese(), "腊")
183 |
184 | lunar = Lunar(fromYmdHms: 113, lunarMonth: -12, lunarDay: 1)
185 | XCTAssertEqual(lunar.getMonthInChinese(), "闰腊")
186 |
187 | lunar = Lunar(fromYmdHms: 5552, lunarMonth: -12, lunarDay: 1)
188 | XCTAssertEqual(lunar.getMonthInChinese(), "闰腊")
189 | }
190 | func testLunar36() throws {
191 | let solar: Solar = Solar(fromYmd: 5553, month: 1, day: 22)
192 | let lunar: Lunar = solar.getLunar()
193 | XCTAssertEqual(lunar.toString(), "五五五二年闰腊月初二")
194 | }
195 |
196 | func testLunar37() throws {
197 | let solar: Solar = Solar(fromYmd: 7013, month: 12, day: 24)
198 | let lunar: Lunar = solar.getLunar()
199 | XCTAssertEqual(lunar.toString(), "七〇一三年闰冬月初四")
200 | }
201 |
202 | func testLunar38() throws {
203 | let lunar: Lunar = Lunar(fromYmdHms: 7013, lunarMonth: -11, lunarDay: 4)
204 | let solar: Solar = lunar.getSolar()
205 | XCTAssertEqual(solar.toString(), "7013-12-24")
206 | }
207 |
208 | func testLunar39() throws {
209 | let solar: Solar = Solar(fromYmd: 1987, month: 4, day: 12)
210 | let lunar: Lunar = solar.getLunar()
211 | XCTAssertEqual(lunar.toString(), "一九八七年三月十五")
212 | }
213 |
214 | func testLunar40() throws {
215 | let solar: Solar = Solar(fromYmd: 1987, month: 4, day: 13)
216 | let lunar: Lunar = solar.getLunar()
217 | XCTAssertEqual(lunar.toString(), "一九八七年三月十六")
218 | }
219 |
220 | func testLunar41() throws {
221 | let solar: Solar = Solar(fromYmd: 4, month: 2, day: 10)
222 | let lunar: Lunar = solar.getLunar()
223 | XCTAssertEqual(lunar.getYearShengXiao(), "鼠")
224 | }
225 |
226 | func testLunar42() throws {
227 | let solar: Solar = Solar(fromYmd: 4, month: 2, day: 9)
228 | let lunar: Lunar = solar.getLunar()
229 | XCTAssertEqual(lunar.getYearShengXiao(), "猪")
230 | }
231 |
232 | func testLunar43() throws {
233 | let solar: Solar = Solar(fromYmd: 1, month: 2, day: 12)
234 | let lunar: Lunar = solar.getLunar()
235 | XCTAssertEqual(lunar.getYearShengXiao(), "鸡")
236 | }
237 |
238 | func testLunar44() throws {
239 | let solar: Solar = Solar(fromYmd: 1, month: 1, day: 1)
240 | let lunar: Lunar = solar.getLunar()
241 | XCTAssertEqual(lunar.getYearShengXiao(), "猴")
242 | }
243 |
244 | func testLunar45() throws {
245 | let solar: Solar = Solar(fromYmd: 2017, month: 2, day: 15)
246 | let lunar: Lunar = solar.getLunar()
247 | XCTAssertEqual(lunar.getDayLu(), "子命互禄 辛命进禄")
248 | }
249 |
250 | func testLunar57() throws {
251 | let solar: Solar = Solar(fromYmd: 1991, month: 2, day: 5)
252 | let lunar: Lunar = solar.getLunar()
253 | XCTAssertEqual(lunar.getMonthInGanZhi(), "庚寅")
254 | }
255 |
256 | func testLunar58() throws {
257 | let solar: Solar = Solar(fromYmd: 2021, month: 3, day: 21)
258 | let lunar: Lunar = solar.getLunar()
259 | XCTAssertEqual(lunar.getOtherFestivals(), ["春社"])
260 | }
261 |
262 | func testLunar59() throws {
263 | let solar: Solar = Solar(fromYmd: 2022, month: 3, day: 16)
264 | let lunar: Lunar = solar.getLunar()
265 | XCTAssertEqual(lunar.getOtherFestivals(), ["春社"])
266 | }
267 |
268 | func testLunar60() throws {
269 | let solar: Solar = Solar(fromYmd: 1722, month: 9, day: 25)
270 | let lunar: Lunar = solar.getLunar()
271 | XCTAssertEqual(lunar.getOtherFestivals(), ["秋社"])
272 | }
273 |
274 | func testLunar61() throws {
275 | let solar: Solar = Solar(fromYmd: 840, month: 9, day: 14)
276 | let lunar: Lunar = solar.getLunar()
277 | XCTAssertEqual(lunar.getOtherFestivals(), ["秋社"])
278 | }
279 | }
280 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/LunarYearTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // LunarYearTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/20.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class LunarYearTests: XCTestCase {
13 | func testLunarYearForFirst() throws {
14 | let year: LunarYear = LunarYear(lunarYear: 2021)
15 | XCTAssertEqual(year.toString(), "2021")
16 | }
17 |
18 | func testLunarYearForSecond() throws {
19 | let year: LunarYear = LunarYear(lunarYear: 2017)
20 | XCTAssertEqual(year.getZhiShui(), "二龙治水")
21 | XCTAssertEqual(year.getFenBing(), "二人分饼")
22 | }
23 |
24 | func testLunarYearForThird() throws {
25 | let year: LunarYear = LunarYear(lunarYear: 2018)
26 | XCTAssertEqual(year.getZhiShui(), "二龙治水")
27 | XCTAssertEqual(year.getFenBing(), "八人分饼")
28 | XCTAssertEqual(year.getDeJin(), "三日得金")
29 | }
30 |
31 | func testLunarYearForFourth() throws {
32 | let year: LunarYear = LunarYear(lunarYear: 2021)
33 | XCTAssertEqual(year.getGengTian(), "十一牛耕田")
34 | }
35 | }
36 |
37 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/MonthTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // MonthTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/20.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class MonthTests: XCTestCase {
12 | func testMonthForFirst() throws {
13 | let month: SolarMonth = SolarMonth(year: 2019, month: 5)
14 | XCTAssertEqual(month.toString(), "2019-5")
15 | XCTAssertEqual(month.toFullString(), "2019年5月")
16 | }
17 |
18 | func testMonthForSecond() throws {
19 | let month: SolarMonth = SolarMonth(year: 2019, month: 5).next(quantity: 1)
20 | XCTAssertEqual(month.toString(), "2019-6")
21 | XCTAssertEqual(month.toFullString(), "2019年6月")
22 | }
23 |
24 | func testMonthForThird() throws {
25 | let month: SolarMonth = SolarMonth(year: 2022, month: 1).next(quantity: -14)
26 | XCTAssertEqual(month.toString(), "2020-11")
27 | XCTAssertEqual(month.toFullString(), "2020年11月")
28 | }
29 |
30 | func testMonthForfourth() throws {
31 | let month: SolarMonth = SolarMonth(year: 2020, month: 11).next(quantity: 14)
32 | XCTAssertEqual(month.toString(), "2022-1")
33 | XCTAssertEqual(month.toFullString(), "2022年1月")
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/PhenologyTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // PhenologyTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class PhenologyTests: XCTestCase {
12 | func testPhenology1() throws {
13 | let solar: Solar = Solar(fromYmd: 2020, month: 4, day: 23);
14 | let lunar: Lunar = solar.getLunar();
15 | XCTAssertEqual(lunar.getPhenology(), "萍始生")
16 | }
17 |
18 | func testPhenology2() throws {
19 | let solar: Solar = Solar(fromYmd: 2021, month: 1, day: 15);
20 | let lunar: Lunar = solar.getLunar();
21 | XCTAssertEqual(lunar.getPhenology(), "雉始雊");
22 | }
23 |
24 | func testPhenology3() throws {
25 | let solar: Solar = Solar(fromYmd: 2017, month: 1, day: 5);
26 | let lunar: Lunar = solar.getLunar();
27 | XCTAssertEqual(lunar.getPhenology(), "雁北乡");
28 | }
29 |
30 | func testPhenology4() throws {
31 | let solar: Solar = Solar(fromYmd: 2020, month: 4, day: 10);
32 | let lunar: Lunar = solar.getLunar();
33 | XCTAssertEqual(lunar.getPhenology(), "田鼠化为鴽");
34 | }
35 |
36 | func testPhenology5() throws {
37 | let solar: Solar = Solar(fromYmd: 2020, month: 6, day: 11);
38 | let lunar: Lunar = solar.getLunar();
39 | XCTAssertEqual(lunar.getPhenology(), "鵙始鸣");
40 | }
41 |
42 | func testPhenology6() throws {
43 | let solar: Solar = Solar(fromYmd: 2020, month: 6, day: 1);
44 | let lunar: Lunar = solar.getLunar();
45 | XCTAssertEqual(lunar.getPhenology(), "麦秋至");
46 | }
47 |
48 | func testPhenology7() throws {
49 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 8);
50 | let lunar: Lunar = solar.getLunar();
51 | XCTAssertEqual(lunar.getPhenology(), "鹖鴠不鸣");
52 | }
53 |
54 | func testPhenology8() throws {
55 | let solar: Solar = Solar(fromYmd: 2020, month: 12, day: 11);
56 | let lunar: Lunar = solar.getLunar();
57 | XCTAssertEqual(lunar.getPhenology(), "鹖鴠不鸣");
58 | }
59 |
60 | func testPhenology9() throws {
61 | let solar: Solar = Solar(fromYmd: 1982, month: 12, day: 22);
62 | let lunar: Lunar = solar.getLunar();
63 | XCTAssertEqual(lunar.getPhenology(), "蚯蚓结");
64 | }
65 |
66 | func testPhenology10() throws {
67 | let solar: Solar = Solar(fromYmd: 2021, month: 12, day: 21);
68 | let lunar: Lunar = solar.getLunar();
69 | XCTAssertEqual(lunar.getSeasonality(), "冬至 初候");
70 | }
71 |
72 | func testPhenology11() throws {
73 | let solar: Solar = Solar(fromYmd: 2021, month: 12, day: 26);
74 | let lunar: Lunar = solar.getLunar();
75 | XCTAssertEqual(lunar.getSeasonality(), "冬至 二候");
76 | }
77 |
78 | func testPhenology12() throws {
79 | let solar: Solar = Solar(fromYmd: 2021, month: 12, day: 31);
80 | let lunar: Lunar = solar.getLunar();
81 | XCTAssertEqual(lunar.getSeasonality(), "冬至 三候");
82 | }
83 |
84 | func testPhenology() throws {
85 | let solar: Solar = Solar(fromYmd: 2022, month: 1, day: 5);
86 | let lunar: Lunar = solar.getLunar();
87 | XCTAssertEqual(lunar.getSeasonality(), "小寒 初候");
88 | }
89 | }
90 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/SessonTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SessonTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/22.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class SessonTests: XCTestCase {
13 | func testSession1() throws {
14 | let sesson: SolarSeason = SolarSeason(year: 2019, month: 5)
15 | XCTAssertEqual(sesson.toString(), "2019.2")
16 | XCTAssertEqual(sesson.toFullString(), "2019年2季度")
17 | }
18 |
19 | func testSession2() throws {
20 | let sesson: SolarSeason = SolarSeason(year: 2019, month: 5).next(seasons: 1)
21 | XCTAssertEqual(sesson.toString(), "2019.3")
22 | XCTAssertEqual(sesson.toFullString(), "2019年3季度")
23 | }
24 |
25 | func testSession3() throws {
26 | let sesson: SolarSeason = SolarSeason(year: 2019, month: 5).next(seasons: -2)
27 | XCTAssertEqual(sesson.toString(), "2018.4")
28 | XCTAssertEqual(sesson.toFullString(), "2018年4季度")
29 | }
30 | }
31 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/ShouXingUtilTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ShouXingUtilTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/21.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class ShouXingUtilTests: XCTestCase {
12 | func testShouXingUtil() throws {
13 | let w: Double = -4778.5306 + 29.5306 * 0
14 |
15 | XCTAssertEqual(ShouXingUtil.calcShuo(jd: w), -4778)
16 |
17 | // let longitude: Double = w + Solar.J2000
18 | // let sw: Double = floor((longitude + 14 - 2451551) / 29.5306) * (Double.pi * 2)
19 |
20 | // XCTAssertEqual(ShouXingUtil.shuoHigh(w: sw), -4778.468923509471)
21 |
22 | let shuoHighparam: Double = -1017.8760197630929
23 | XCTAssertEqual(ShouXingUtil.msaLonT2(w: shuoHighparam), -0.13083645768655663)
24 |
25 | XCTAssertEqual(ShouXingUtil.mLon(t: -0.13003072702394278, n: 20), -1088.4037694835754)
26 | }
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/SolarTermsTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarTermsTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/20.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class SolarTermsTests: XCTestCase {
12 | func testSolarTerms1() throws {
13 | let solar = Solar(fromYmd: 1986, month: 1, day: 5)
14 | let lunar: Lunar = solar.getLunar()
15 | XCTAssertEqual(lunar.getJie(), "小寒")
16 | XCTAssertEqual(lunar.getJieQi(), "小寒")
17 | XCTAssertEqual(lunar.currentJie?.name, "小寒")
18 | XCTAssertNil(lunar.currentQi)
19 | XCTAssertEqual(lunar.getQi(),"")
20 | XCTAssertEqual(lunar.getPrevJie().name, "大雪")
21 | XCTAssertEqual(lunar.getPrevQi().name, "冬至")
22 | XCTAssertEqual(lunar.getPrevJieQi().name, "冬至")
23 | }
24 |
25 | func testSolarTerms2() throws {
26 | let solar = Solar(fromYmdHms: 1986, month: 1, day: 20, hour: 17, minute: 0, second: 0)
27 | let lunar: Lunar = solar.getLunar()
28 | XCTAssertEqual(lunar.getJie(), "")
29 | XCTAssertEqual(lunar.getJieQi(), "大寒")
30 | XCTAssertNil(lunar.currentJie)
31 | XCTAssertEqual(lunar.currentJieQi!.name, "大寒")
32 | XCTAssertNil(lunar.currentJie)
33 | XCTAssertEqual(lunar.getQi(), "大寒")
34 | XCTAssertEqual(lunar.getNextJie().name, "立春")
35 | XCTAssertEqual(lunar.getNextQi().name, "雨水")
36 | XCTAssertEqual(lunar.getNextJieQi().name, "立春")
37 | }
38 |
39 | func testSolarTerms3() throws {
40 | let solar = Solar(fromYmdHms: 1986, month: 1, day: 20, hour: 14, minute: 0, second: 0)
41 | let lunar: Lunar = solar.getLunar()
42 | XCTAssertEqual(lunar.getPrevJie().name, "小寒")
43 | XCTAssertEqual(lunar.getPrevQi().name, "冬至")
44 | XCTAssertEqual(lunar.getPrevJieQi().name, "小寒")
45 | }
46 |
47 | func testSolarTerms4() throws {
48 | let solar = Solar(fromYmd: 1986, month: 12, day: 7)
49 | let lunar: Lunar = solar.getLunar()
50 | XCTAssertEqual(lunar.getJie(), "大雪")
51 | XCTAssertEqual(lunar.getJieQi(), "大雪")
52 | XCTAssertEqual(lunar.currentJie!.name, "大雪")
53 | XCTAssertEqual(lunar.currentJieQi!.name, "大雪")
54 | XCTAssertNil(lunar.currentQi)
55 | XCTAssertEqual(lunar.getQi(), "")
56 | XCTAssertEqual(lunar.getNextJie().name, "大雪")
57 | XCTAssertEqual(lunar.getNextQi().name, "冬至")
58 | XCTAssertEqual(lunar.getNextJieQi().name, "大雪")
59 | }
60 | func testSolarTerms5() throws {
61 | let solar = Solar(fromYmd: 1986, month: 1, day: 1)
62 | let lunar: Lunar = solar.getLunar()
63 | XCTAssertEqual(lunar.getJie(), "")
64 | XCTAssertEqual(lunar.getJieQi(), "")
65 | XCTAssertNil(lunar.currentJie)
66 | XCTAssertNil(lunar.currentJieQi)
67 | XCTAssertNil(lunar.currentQi)
68 | XCTAssertEqual(lunar.getQi(), "")
69 | XCTAssertEqual(lunar.getPrevJie().name, "大雪")
70 | XCTAssertEqual(lunar.getPrevQi().name, "冬至")
71 | XCTAssertEqual(lunar.getPrevJieQi().name, "冬至")
72 | XCTAssertEqual(lunar.getNextJie().name, "小寒")
73 | XCTAssertEqual(lunar.getNextQi().name, "大寒")
74 | XCTAssertEqual(lunar.getNextJieQi().name, "小寒")
75 | }
76 |
77 | func testSolarTerms6() throws {
78 | let solar = Solar(fromYmd: 1986, month: 1, day: 1)
79 | let lunar: Lunar = solar.getLunar()
80 | XCTAssertEqual(lunar.getJie(), "")
81 | XCTAssertEqual(lunar.getJieQi(), "")
82 | XCTAssertNil(lunar.currentJie)
83 | XCTAssertNil(lunar.currentJieQi)
84 | XCTAssertNil(lunar.currentQi)
85 | XCTAssertEqual(lunar.getQi(), "")
86 | XCTAssertEqual(lunar.getPrevJie().name, "大雪")
87 | XCTAssertEqual(lunar.getPrevQi().name, "冬至")
88 | XCTAssertEqual(lunar.getPrevJieQi().name, "冬至")
89 | XCTAssertEqual(lunar.getNextJie().name, "小寒")
90 | XCTAssertEqual(lunar.getNextQi().name, "大寒")
91 | XCTAssertEqual(lunar.getNextJieQi().name, "小寒")
92 | }
93 |
94 | func testSolarTerms7() throws {
95 | let solarTermsTable: [String: String] = [
96 | "冬至": "2021-12-21 23:59:09",
97 | "小寒": "2022-01-05 17:13:54",
98 | "大寒": "2022-01-20 10:38:56",
99 | "立春": "2022-02-04 04:50:36",
100 | "雨水": "2022-02-19 00:42:50",
101 | "惊蛰": "2022-03-05 22:43:34",
102 | "春分": "2022-03-20 23:33:15",
103 | "清明": "2022-04-05 03:20:03",
104 | "谷雨": "2022-04-20 10:24:07",
105 | "立夏": "2022-05-05 20:25:46",
106 | "小满": "2022-05-21 09:22:25",
107 | "芒种": "2022-06-06 00:25:37",
108 | "夏至": "2022-06-21 17:13:40",
109 | "小暑": "2022-07-07 10:37:49",
110 | "大暑": "2022-07-23 04:06:49",
111 | "立秋": "2022-08-07 20:28:57",
112 | "处暑": "2022-08-23 11:15:59",
113 | "白露": "2022-09-07 23:32:07",
114 | "秋分": "2022-09-23 09:03:31",
115 | "寒露": "2022-10-08 15:22:16",
116 | "霜降": "2022-10-23 18:35:31",
117 | "立冬": "2022-11-07 18:45:18",
118 | "小雪": "2022-11-22 16:20:18",
119 | "大雪": "2022-12-07 11:46:04"
120 | ]
121 | let solar: Solar = Solar(fromYmd: 2022, month: 7, day: 15)
122 | let result: [String: Solar] = solar.getLunar().getJieQiTable()
123 | for entry in solarTermsTable {
124 | let name: String = entry.key
125 | XCTAssertEqual(result[name]!.toYmdHms(), entry.value)
126 | }
127 | }
128 |
129 | func testSolarTerms8() throws {
130 | let solarTermsTable: [String: String] = [
131 | "冬至": "1985-12-22 06:07:40",
132 | "小寒": "1986-01-05 23:28:02",
133 | "大寒": "1986-01-20 16:46:12",
134 | "立春": "1986-02-04 11:07:42",
135 | "雨水": "1986-02-19 06:57:31",
136 | "惊蛰": "1986-03-06 05:12:08",
137 | "春分": "1986-03-21 06:02:41",
138 | "清明": "1986-04-05 10:06:07",
139 | "谷雨": "1986-04-20 17:12:08",
140 | "立夏": "1986-05-06 03:30:36",
141 | "小满": "1986-05-21 16:27:55",
142 | "芒种": "1986-06-06 07:44:23",
143 | "夏至": "1986-06-22 00:29:57",
144 | "小暑": "1986-07-07 18:00:45",
145 | "大暑": "1986-07-23 11:24:23",
146 | "立秋": "1986-08-08 03:45:36",
147 | "处暑": "1986-08-23 18:25:47",
148 | "白露": "1986-09-08 06:34:37",
149 | "秋分": "1986-09-23 15:58:52",
150 | "寒露": "1986-10-08 22:06:45",
151 | "霜降": "1986-10-24 01:14:11",
152 | "立冬": "1986-11-08 01:12:49",
153 | "小雪": "1986-11-22 22:44:20",
154 | "大雪": "1986-12-07 18:00:56"
155 | ]
156 | let solar: Solar = Solar(fromYmd: 1986, month: 7, day: 15)
157 | let result: [String: Solar] = solar.getLunar().getJieQiTable()
158 | for entry in solarTermsTable {
159 | let name: String = entry.key
160 | XCTAssertEqual(result[name]!.toYmdHms(), entry.value)
161 | }
162 | }
163 |
164 | func testSolarTerms9() throws {
165 | let lunar: Lunar = Lunar(fromYmdHms: 2012, lunarMonth: 9, lunarDay: 1)
166 | XCTAssertEqual(lunar.getJieQiTable()["白露"]!.toYmdHms(), "2012-09-07 13:29:00")
167 | }
168 |
169 | func testSolarTerms10() throws {
170 | let lunar: Lunar = Lunar(fromYmdHms: 2050, lunarMonth: 12, lunarDay: 1)
171 | XCTAssertEqual(lunar.getJieQiTable()["大雪"]!.toYmdHms(), "2050-12-07 06:41:00")
172 | }
173 |
174 | func testSolarTerms11() throws {
175 | let solar: Solar = Solar(fromYmd: 2021, month: 12, day: 21)
176 | let lunar: Lunar = solar.getLunar()
177 | XCTAssertEqual(lunar.getJieQi(), "冬至")
178 | XCTAssertEqual(lunar.getJie(), "")
179 | XCTAssertEqual(lunar.getQi(), "冬至")
180 | }
181 | }
182 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/SolarTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/12.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class SolarTests: XCTestCase {
13 | func testSolar() throws {
14 | // This is an example of a functional test case.
15 | // Use XCTAssert and related functions to verify your tests produce the correct
16 | // results.
17 | let solar: Solar = Solar(fromYmd: 2019, month: 5, day: 1)
18 | XCTAssertEqual(solar.toString(), "2019-05-01")
19 | XCTAssertEqual(solar.toFullString(), "2019-05-01 00:00:00 星期三 (劳动节) 金牛座")
20 | // XCTAssertEqual(solar.getLunar().toString(), "二〇一九年三月廿七")
21 | // XCTAssertEqual(solar.getLunar().toFullString(), "二〇一九年三月廿七 己亥(猪)年 戊辰(龙)月 戊戌(狗)日 子(鼠)时 纳音[平地木 大林木 平地木 桑柘木] 星期三 西方白虎 星宿[参水猿](吉) 彭祖百忌[戊不受田田主不祥 戌不吃犬作怪上床] 喜神方位[巽](东南) 阳贵神方位[艮](东北) 阴贵神方位[坤](西南) 福神方位[艮](东北) 财神方位[坎](正北) 冲[(壬辰)龙] 煞[北]")
22 | }
23 |
24 | func testFromYmd() throws {
25 | var solar: Solar = Solar(fromYmd: 2020, month: 1, day: 23)
26 | XCTAssertEqual(solar.next(days: 1).toString(), "2020-01-24")
27 | /// 仅工作日,跨越春节假期
28 | XCTAssertEqual(solar.next(days: 1, onlyWorkday: true).toString(), "2020-02-03")
29 |
30 | solar = Solar(fromYmd: 2020, month: 2, day: 3)
31 | XCTAssertEqual(solar.next(days: -3).toString(), "2020-01-31")
32 | /// 仅工作日,跨越春节假期
33 | XCTAssertEqual(solar.next(days: -3, onlyWorkday: true).toString(), "2020-01-21")
34 |
35 | solar = Solar(fromYmd: 2020, month: 2, day: 9)
36 | XCTAssertEqual(solar.next(days: 6).toString(), "2020-02-15")
37 | /// 仅工作日,跨越周末
38 | XCTAssertEqual(solar.next(days: 6, onlyWorkday: true).toString(), "2020-02-17")
39 |
40 | solar = Solar(fromYmd: 2020, month: 1, day: 17)
41 | XCTAssertEqual(solar.next(days: 1).toString(), "2020-01-18")
42 | /// 仅工作日,周日调休按上班算
43 | XCTAssertEqual(solar.next(days: 1, onlyWorkday: true).toString(), "2020-01-19")
44 | }
45 |
46 | func testIsLeepYear() throws {
47 | XCTAssertEqual(SolarUtil.isLeapYear(year: 1500), false)
48 | }
49 |
50 | func testSolarGetterAndSetter() {
51 | let dateFormat: DateFormatter = DateFormatter()
52 | dateFormat.dateFormat = "yyyy-MM-dd HH:mm:ss"
53 | let date: Date = dateFormat.date(from: "2022-07-22 18:59:56")!
54 | let solar: Solar = Solar(fromDate: date)
55 | // let lunar: Lunar = solar.getLunar()
56 | XCTAssertEqual(solar.calendar, date)
57 | }
58 | }
59 |
60 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/SolarWeekTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // SolarWeekTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/20.
6 | //
7 |
8 | import XCTest
9 | @testable import SwiftLunar
10 |
11 | @available(macOS 12.0, *)
12 | final class SolarWeekTests: XCTestCase {
13 | func testSolarWeekForFirst() throws {
14 | let week: SolarWeek = SolarWeek(year: 2021, month: 5, day: 1, start: 0)
15 | XCTAssertEqual(week.index, 1)
16 | }
17 |
18 | func testSolarWeekForSecond() throws {
19 | let week: SolarWeek = SolarWeek(year: 2021, month: 5, day: 4, start: 2)
20 | XCTAssertEqual(week.index, 2)
21 | }
22 |
23 | func testSolarWeekForThird() throws {
24 | let week: SolarWeek = SolarWeek(year: 2022, month: 5, day: 1, start: 0)
25 | XCTAssertEqual(week.index, 1)
26 | }
27 |
28 | func testSolarWeekForFourth() throws {
29 | let week: SolarWeek = SolarWeek(year: 2022, month: 5, day: 1, start: 1)
30 | XCTAssertEqual(week.index, 1)
31 | }
32 |
33 | func testSolarWeekForFifth() throws {
34 | let week: SolarWeek = SolarWeek(year: 2022, month: 3, day: 6, start: 0)
35 | XCTAssertEqual(week.getIndexInYear(), 11)
36 | }
37 | }
38 |
39 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/TaoistTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TaoistTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class TaoistTests: XCTestCase {
12 | func testTaoist1() throws {
13 | let taoist: Taoist = Taoist.fromLunar(lunar: Lunar(fromYmdHms: 2021, lunarMonth: 10, lunarDay: 17, hour: 18, minute: 0, second: 0))
14 | XCTAssertEqual(taoist.toString(), "四七一八年十月十七")
15 | XCTAssertEqual(taoist.toFullString(), "道歷四七一八年,天運辛丑年,己亥月,癸酉日。十月十七日,酉時。")
16 | }
17 |
18 | func testTaoist2() throws {
19 | let taoist1: Taoist = Taoist.fromYmd(year: 4718, month: 10, day: 18);
20 | var l1: [String] = []
21 | for taoistFestival in taoist1.getFestivals() {
22 | l1.append(taoistFestival.name)
23 | }
24 | XCTAssertEqual(l1, ["地母娘娘圣诞", "四时会"])
25 |
26 |
27 | let taoist2 = Lunar(fromYmdHms: 2021, lunarMonth: 10, lunarDay: 18).getTaoist()
28 | var l2: [String] = []
29 | for taoistFestival in taoist2.getFestivals() {
30 | l2.append(taoistFestival.name)
31 | }
32 | XCTAssertEqual(l2, ["地母娘娘圣诞", "四时会"])
33 | }
34 | }
35 |
36 |
--------------------------------------------------------------------------------
/Tests/SwiftLunarTests/TimeTests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TimeTests.swift
3 | //
4 | //
5 | // Created by 睿宁 on 2022/7/23.
6 | //
7 | import XCTest
8 | @testable import SwiftLunar
9 |
10 | @available(macOS 12.0, *)
11 | final class TimeTests: XCTestCase {
12 | func testTime1() throws {
13 | let timeTable: [String: String] = [
14 | "23:00": "子",
15 | "00:59": "子",
16 | "23:30": "子",
17 | "01:00": "丑",
18 | "02:59": "丑",
19 | "01:30": "丑",
20 | "03:00": "寅",
21 | "04:59": "寅",
22 | "03:30": "寅",
23 | "05:00": "卯",
24 | "06:59": "卯",
25 | "05:30": "卯",
26 | "07:00": "辰",
27 | "08:59": "辰",
28 | "07:30": "辰",
29 | "09:00": "巳",
30 | "10:59": "巳",
31 | "09:30": "巳",
32 | "11:00": "午",
33 | "12:59": "午",
34 | "11:30": "午",
35 | "13:00": "未",
36 | "14:59": "未",
37 | "13:30": "未",
38 | "15:00": "申",
39 | "16:59": "申",
40 | "15:30": "申",
41 | "17:00": "酉",
42 | "18:59": "酉",
43 | "17:30": "酉",
44 | "19:00": "戌",
45 | "20:59": "戌",
46 | "19:30": "戌",
47 | "21:00": "亥",
48 | "22:59": "亥",
49 | "21:30": "亥",
50 | "": "子",
51 | "23:01:01": "子",
52 | "其他": "子",
53 | "21:01:01": "亥"
54 | ]
55 | for entry in timeTable {
56 | let hm: String = entry.key
57 | let zhi: String = entry.value
58 | XCTAssertEqual(LunarUtil.convertTime(hm: hm), zhi)
59 | }
60 | }
61 |
62 | func testTime2() throws {
63 | let timeTable: [String: String] = [
64 | "2020-4,5,23:00": "戊",
65 | //早子时
66 | "2020-4,5,00:59": "丙",
67 | //晚子时
68 | "2020-4,5,23:30": "戊",
69 |
70 | "2020-4,5,01:00": "丁",
71 | "2020-4,5,02:59": "丁",
72 | "2020-4,5,01:30": "丁",
73 |
74 | "2020-4,5,03:00": "戊",
75 | "2020-4,5,04:59": "戊",
76 | "2020-4,5,03:30": "戊",
77 |
78 | "2020-4,5,05:00": "己",
79 | "2020-4,5,06:59": "己",
80 | "2020-4,5,05:30": "己",
81 |
82 | "2020-4,5,07:00": "庚",
83 | "2020-4,5,08:59": "庚",
84 | "2020-4,5,07:30": "庚",
85 |
86 | "2020-4,5,09:00": "辛",
87 | "2020-4,5,10:59": "辛",
88 | "2020-4,5,09:30": "辛",
89 |
90 | "2020-4,5,11:00": "壬",
91 | "2020-4,5,12:59": "壬",
92 | "2020-4,5,11:30": "壬",
93 |
94 | "2020-4,5,13:00": "癸",
95 | "2020-4,5,14:59": "癸",
96 | "2020-4,5,13:30": "癸",
97 |
98 | "2020-4,5,15:00": "甲",
99 | "2020-4,5,16:59": "甲",
100 | "2020-4,5,15:30": "甲",
101 |
102 | "2020-4,5,17:00": "乙",
103 | "2020-4,5,18:59": "乙",
104 | "2020-4,5,17:30": "乙",
105 |
106 | "2020-4,5,19:00": "丙",
107 | "2020-4,5,20:59": "丙",
108 | "2020-4,5,19:30": "丙",
109 |
110 | "2020-4,5,21:00": "丁",
111 | "2020-4,5,22:59": "丁",
112 | "2020-4,5,21:30": "丁",
113 |
114 | "2020-4,5,null": "丙",
115 |
116 | "2020-4,5,": "丙",
117 | "2020-4,5,23:01:01": "戊",
118 | "2020-4,5,其他": "丙",
119 | "2020-4,5,80:90": "丙",
120 |
121 | "2020-4,5,21:01:01": "丁",
122 |
123 | "2020-4,2,23:00": "壬",
124 | "2020-4,2,11:20": "丙"
125 | ]
126 | for entry in timeTable {
127 | var hour: Int = 0, minute: Int = 0
128 | let time: String = entry.key
129 | let year: Int = Int(time.prefix(4))!
130 | let month: Int = Int(time[time.index(time.startIndex, offsetBy: 4)..= 5) {
134 | hour = Int(hm.prefix(2))!
135 | minute = Int(hm[hm.index(hm.startIndex, offsetBy: 3)..= 5) {
219 | hour = Int(hm.prefix(2))!
220 | minute = Int(hm[hm.index(hm.startIndex, offsetBy: 3)..