Date+Extension.swift 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639
  1. //
  2. // Date+Extension.swift
  3. // QuickSearchLocation
  4. //
  5. // Created by Destiny on 2024/4/15.
  6. //
  7. import Foundation
  8. public enum TimestampType: Int {
  9. /// 秒
  10. case second
  11. /// 毫秒
  12. case millisecond
  13. }
  14. public extension Date {
  15. // MARK: 1.1、获取当前 秒级 时间戳 - 10 位
  16. /// 获取当前 秒级 时间戳 - 10 位
  17. static var secondStamp : String {
  18. let timeInterval: TimeInterval = Date().timeIntervalSince1970
  19. return "\(Int(timeInterval))"
  20. }
  21. // MARK: 1.2、获取当前 毫秒级 时间戳 - 13 位
  22. /// 获取当前 毫秒级 时间戳 - 13 位
  23. static var milliStamp : String {
  24. let timeInterval: TimeInterval = Date().timeIntervalSince1970
  25. let millisecond = CLongLong(round(timeInterval*1000))
  26. return "\(millisecond)"
  27. }
  28. // MARK: 1.3、获取当前的时间 Date
  29. /// 获取当前的时间 Date
  30. static var currentDate : Date {
  31. return Date()
  32. }
  33. // MARK: 1.4、从 Date 获取年份
  34. /// 从 Date 获取年份
  35. var year: Int {
  36. return Calendar.current.component(Calendar.Component.year, from: self)
  37. }
  38. // MARK: 1.5、从 Date 获取月份
  39. /// 从 Date 获取年份
  40. var month: Int {
  41. return Calendar.current.component(Calendar.Component.month, from: self)
  42. }
  43. // MARK: 1.6、从 Date 获取 日
  44. /// 从 Date 获取 日
  45. var day: Int {
  46. return Calendar.current.component(.day, from: self)
  47. }
  48. // MARK: 1.7、从 Date 获取 小时
  49. /// 从 Date 获取 日
  50. var hour: Int {
  51. return Calendar.current.component(.hour, from: self)
  52. }
  53. // MARK: 1.8、从 Date 获取 分钟
  54. /// 从 Date 获取 分钟
  55. var minute: Int {
  56. return Calendar.current.component(.minute, from: self)
  57. }
  58. // MARK: 1.9、从 Date 获取 秒
  59. /// 从 Date 获取 秒
  60. var second: Int {
  61. return Calendar.current.component(.second, from: self)
  62. }
  63. // MARK: 1.10、从 Date 获取 毫秒
  64. /// 从 Date 获取 毫秒
  65. var nanosecond: Int {
  66. return Calendar.current.component(.nanosecond, from: self)
  67. }
  68. // MARK: 1.11、从日期获取 星期(英文)
  69. /// 从日期获取 星期
  70. var weekday: String {
  71. qsl_formatter.dateFormat = "EEEE"
  72. return qsl_formatter.string(from: self)
  73. }
  74. // MARK: 1.12、从日期获取 星期(中文)
  75. var weekdayStringFromDate: String {
  76. let weekdays = ["星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"]
  77. var calendar = Calendar(identifier: .gregorian)
  78. let timeZone = TimeZone(identifier: "Asia/Shanghai")
  79. calendar.timeZone = timeZone!
  80. let theComponents = calendar.dateComponents([.weekday], from: self as Date)
  81. return weekdays[theComponents.weekday! - 1]
  82. }
  83. // 现在日期的格式化形式
  84. var formateCurrentDate: String {
  85. qsl_formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
  86. return qsl_formatter.string(from: Date())
  87. }
  88. // MARK: 1.13、从日期获取 月(英文)
  89. /// 从日期获取 月(英文)
  90. var monthAsString: String {
  91. qsl_formatter.dateFormat = "MM"
  92. return qsl_formatter.string(from: self)
  93. }
  94. }
  95. //MARK: - 二、时间格式的转换
  96. // MARK: 时间条的显示格式
  97. public enum JKTimeBarType {
  98. // 默认格式,如 9秒:09,66秒:01:06,
  99. case normal
  100. case second
  101. case minute
  102. case hour
  103. }
  104. public extension Date {
  105. // MARK: 2.1、时间戳(支持10位和13位)按照对应的格式 转化为 对应时间的字符串
  106. /// 时间戳(支持10位和13位)按照对应的格式 转化为 对应时间的字符串 如:1603849053 按照 "yyyy-MM-dd HH:mm:ss" 转化后为:2020-10-28 09:37:33
  107. /// - Parameters:
  108. /// - timestamp: 时间戳
  109. /// - format: 格式
  110. /// - Returns: 对应时间的字符串
  111. static func timestampToFormatterTimeString(timestamp: String, format: String = "yyyy-MM-dd HH:mm:ss") -> String {
  112. // 时间戳转为Date
  113. let date = timestampToFormatterDate(timestamp: timestamp)
  114. // let dateFormatter = DateFormatter()
  115. // 设置 dateFormat
  116. qsl_formatter.dateFormat = format
  117. // 按照dateFormat把Date转化为String
  118. return qsl_formatter.string(from: date)
  119. }
  120. // MARK: 2.2、时间戳(支持 10 位 和 13 位) 转 Date
  121. /// 时间戳(支持 10 位 和 13 位) 转 Date
  122. /// - Parameter timestamp: 时间戳
  123. /// - Returns: 返回 Date
  124. static func timestampToFormatterDate(timestamp: String) -> Date {
  125. guard timestamp.count == 10 || timestamp.count == 13 else {
  126. #if DEBUG
  127. fatalError("时间戳位数不是 10 也不是 13")
  128. #else
  129. return Date()
  130. #endif
  131. }
  132. guard let timestampInt = Int(timestamp) else {
  133. #if DEBUG
  134. fatalError("时间戳位有问题")
  135. #else
  136. return Date()
  137. #endif
  138. }
  139. let timestampValue = timestamp.count == 10 ? timestampInt : timestampInt / 1000
  140. // 时间戳转为Date
  141. let date = Date(timeIntervalSince1970: TimeInterval(timestampValue))
  142. return date
  143. }
  144. /// 根据本地时区转换
  145. private static func getNowDateFromatAnDate(_ anyDate: Date?) -> Date? {
  146. // 设置源日期时区
  147. let sourceTimeZone = NSTimeZone(abbreviation: "UTC")
  148. // 或GMT
  149. // 设置转换后的目标日期时区
  150. let destinationTimeZone = NSTimeZone.local as NSTimeZone
  151. // 得到源日期与世界标准时间的偏移量
  152. var sourceGMTOffset: Int? = nil
  153. if let aDate = anyDate {
  154. sourceGMTOffset = sourceTimeZone?.secondsFromGMT(for: aDate)
  155. }
  156. // 目标日期与本地时区的偏移量
  157. var destinationGMTOffset: Int? = nil
  158. if let aDate = anyDate {
  159. destinationGMTOffset = destinationTimeZone.secondsFromGMT(for: aDate)
  160. }
  161. // 得到时间偏移量的差值
  162. let interval = TimeInterval((destinationGMTOffset ?? 0) - (sourceGMTOffset ?? 0))
  163. // 转为现在时间
  164. var destinationDateNow: Date? = nil
  165. if let aDate = anyDate {
  166. destinationDateNow = Date(timeInterval: interval, since: aDate)
  167. }
  168. return destinationDateNow
  169. }
  170. // MARK: 2.3、Date 转换为相应格式的时间字符串,如 Date 转为 2020-10-28
  171. /// Date 转换为相应格式的字符串,如 Date 转为 2020-10-28
  172. /// - Parameter format: 转换的格式
  173. /// - Returns: 返回具体的字符串
  174. func toformatterTimeString(formatter: String = "yyyy-MM-dd HH:mm:ss") -> String {
  175. // let dateFormatter = DateFormatter()
  176. qsl_formatter.timeZone = TimeZone.autoupdatingCurrent
  177. qsl_formatter.dateFormat = formatter
  178. return qsl_formatter.string(from: self)
  179. }
  180. // MARK: 2.4、带格式的时间转 时间戳,支持返回 13位 和 10位的时间戳,时间字符串和时间格式必须保持一致
  181. /// 带格式的时间转 时间戳,支持返回 13位 和 10位的时间戳,时间字符串和时间格式必须保持一致
  182. /// - Parameters:
  183. /// - timeString: 时间字符串,如:2020-10-26 16:52:41
  184. /// - formatter: 时间格式,如:yyyy-MM-dd HH:mm:ss
  185. /// - timestampType: 返回的时间戳类型,默认是秒 10 为的时间戳字符串
  186. /// - Returns: 返回转化后的时间戳
  187. static func formatterTimeStringToTimestamp(timesString: String, formatter: String, timestampType: TimestampType = .second) -> String {
  188. qsl_formatter.dateFormat = formatter
  189. qsl_formatter.locale = NSLocale.system
  190. guard let date = qsl_formatter.date(from: timesString) else {
  191. #if DEBUG
  192. fatalError("日期格式不匹配")
  193. #else
  194. return ""
  195. #endif
  196. }
  197. if timestampType == .second {
  198. return "\(Int(date.timeIntervalSince1970))"
  199. }
  200. return "\(Int((date.timeIntervalSince1970) * 1000))"
  201. }
  202. // MARK: 2.5、带格式的时间转 Date
  203. /// 带格式的时间转 Date
  204. /// - Parameters:
  205. /// - timesString: 时间字符串
  206. /// - formatter: 格式
  207. /// - Returns: 返回 Date
  208. static func formatterTimeStringToDate(timesString: String, formatter: String) -> Date {
  209. qsl_formatter.dateFormat = formatter
  210. qsl_formatter.locale = NSLocale.system
  211. guard let date = qsl_formatter.date(from: timesString) else {
  212. #if DEBUG
  213. fatalError("时间有问题")
  214. #else
  215. return Date()
  216. #endif
  217. }
  218. /*
  219. guard let resultDate = getNowDateFromatAnDate(date) else {
  220. return Date()
  221. }
  222. */
  223. return date
  224. }
  225. // MARK: 2.6、秒转换成播放时间条的格式
  226. /// 秒转换成播放时间条的格式
  227. /// - Parameters:
  228. /// - secounds: 秒数
  229. /// - type: 格式类型
  230. /// - Returns: 返回时间条
  231. static func getFormatPlayTime(seconds: Int, type: JKTimeBarType = .normal) -> String {
  232. if seconds <= 0{
  233. return "00:00"
  234. }
  235. // 秒
  236. let second = seconds % 60
  237. if type == .second {
  238. return String(format: "%02d", seconds)
  239. }
  240. // 分钟
  241. var minute = Int(seconds / 60)
  242. if type == .minute {
  243. return String(format: "%02d:%02d", minute, second)
  244. }
  245. // 小时
  246. var hour = 0
  247. if minute >= 60 {
  248. hour = Int(minute / 60)
  249. minute = minute - hour * 60
  250. }
  251. if type == .hour {
  252. return String(format: "%02d:%02d:%02d", hour, minute, second)
  253. }
  254. // normal 类型
  255. if hour > 0 {
  256. return String(format: "%02d:%02d:%02d", hour, minute, second)
  257. }
  258. if minute > 0 {
  259. return String(format: "%02d:%02d", minute, second)
  260. }
  261. return String(format: "%02d", second)
  262. }
  263. // MARK: 2.7、Date 转 时间戳
  264. /// Date 转 时间戳
  265. /// - Parameter timestampType: 返回的时间戳类型,默认是秒 10 为的时间戳字符串
  266. /// - Returns: 时间戳
  267. func dateToTimeStamp(timestampType: TimestampType = .second) -> String {
  268. // 10位数时间戳 和 13位数时间戳
  269. let interval = timestampType == .second ? CLongLong(Int(self.timeIntervalSince1970)) : CLongLong(round(self.timeIntervalSince1970 * 1000))
  270. return "\(interval)"
  271. }
  272. // 转成当前时区的日期
  273. func dateFromGMT() -> Date {
  274. let secondFromGMT: TimeInterval = TimeInterval(TimeZone.current.secondsFromGMT(for: self))
  275. return self.addingTimeInterval(secondFromGMT)
  276. }
  277. }
  278. // MARK: - 三、本地化时间格式的转换(在日期及其文本表示形式之间进行转换的格式化)
  279. public extension Date {
  280. //MARK: 3.1、date使用DateFormatter.Style的形式格式化(传本地化字符串)
  281. /// date使用DateFormatter.Style的形式格式化(传本地化字符串)
  282. /// - Parameters:
  283. /// - localIdentifier: 本地化语言字符串
  284. /// - formatter: 格式
  285. /// - dateStyle: 日期格式
  286. /// - timeStyle: 时间格式
  287. /// - timeZone: 时区
  288. /// - Returns: 返回对应的格式化后的时间
  289. ///
  290. /// - Note:在向用户显示日期时,可以根据您的具体需要设置 date formatter 的dateStyle和timeStyle属性。例如,如果您想要显示月份、日期和年份而不显示时间,则可以将dateStyle属性设置为DateFormatter.Style.long 并且将timeStyle属性设置为DateFormatter. Style.none 。相反,如果您只想显示时间,您可以将dateStyle属性设置为DateFormatter.Style.none 并且将timeStyle属性设置为DateFormatter.Style.short。DateFormatter根据dateStyle和timeStyle属性的值,提供适合于给定语言环境的指定日期的表示
  291. func toLocalDateFormatterStyleString(localIdentifier: String = "zh_CN" , formatter: String = "yyyyMMMd", dateStyle: DateFormatter.Style = .short, timeStyle: DateFormatter.Style = .none, timeZone: TimeZone = TimeZone.autoupdatingCurrent) -> String {
  292. return toLocalDateFormatterStyleString(locale: Locale(identifier: localIdentifier), formatter: formatter, dateStyle: dateStyle, timeStyle: timeStyle, timeZone: timeZone)
  293. }
  294. //MARK: 3.2、date使用DateFormatter.Style的形式格式化(传本地化Locale对象)
  295. /// date使用DateFormatter.Style的形式格式化(传Locale对象)
  296. /// - Parameters:
  297. /// - locale: 本地化Locale对象
  298. /// - formatter: 格式
  299. /// - dateStyle: 日期格式
  300. /// - timeStyle: 时间格式
  301. /// - timeZone: 时区
  302. /// - Returns: 返回对应的格式化后的时间
  303. func toLocalDateFormatterStyleString(locale: Locale = Locale.current, formatter: String = "yyyyMMMd", dateStyle: DateFormatter.Style = .short, timeStyle: DateFormatter.Style = .none, timeZone: TimeZone = TimeZone.autoupdatingCurrent) -> String {
  304. let dateFormatter = DateFormatter()
  305. dateFormatter.timeZone = timeZone
  306. dateFormatter.dateStyle = .short
  307. dateFormatter.timeStyle = timeStyle
  308. dateFormatter.setLocalizedDateFormatFromTemplate(formatter)
  309. dateFormatter.locale = locale
  310. return dateFormatter.string(from: self)
  311. }
  312. //MARK: 3.3、date使用locale和formatter的形式格式化(传本地化字符串)
  313. /// date使用locale和formatter的形式格式化(传本地化字符串)
  314. /// - Parameters:
  315. /// - localIdentifier: 本地化语言字符串
  316. /// - formatter: 格式
  317. /// - timeZone: 时区
  318. /// - Returns: 返回对应的格式化后的时间
  319. func toFormatterLocalTimeString(localIdentifier: String = "zh_CN", formatter: String = "yyyyMMMd", timeZone: TimeZone = TimeZone.autoupdatingCurrent) -> String {
  320. return toformatterLocalTimeString(locale: Locale(identifier: localIdentifier), formatter: formatter, timeZone: timeZone)
  321. }
  322. //MARK: 3.4、date使用locale和formatter的形式格式化(传本地化Locale对象)
  323. /// date使用locale和formatter的形式格式化(传本地化Locale对象)
  324. /// - Parameters:
  325. /// - locale: 本地化Locale对象
  326. /// - formatter: 格式
  327. /// - timeZone: 时区
  328. /// - Returns: 返回对应的格式化后的时间
  329. func toformatterLocalTimeString(locale: Locale = Locale.current, formatter: String = "yyyyMMMd", timeZone: TimeZone = TimeZone.autoupdatingCurrent) -> String {
  330. let dateFormatter = DateFormatter()
  331. dateFormatter.timeZone = timeZone
  332. dateFormatter.setLocalizedDateFormatFromTemplate(formatter)
  333. dateFormatter.locale = locale
  334. return dateFormatter.string(from: self)
  335. }
  336. }
  337. // MARK: - 四、前天、昨天、今天、明天、后天、是否同一年同一月同一天 的判断
  338. public extension Date {
  339. // MARK: 4.1、今天的日期
  340. /// 今天的日期
  341. static var todayDate: Date {
  342. return Date()
  343. }
  344. // MARK: 4.2、昨天的日期(相对于date的昨天日期)
  345. /// 昨天的日期
  346. static var yesterDayDate: Date? {
  347. return Calendar.current.date(byAdding: DateComponents(day: -1), to: Date())
  348. }
  349. // MARK: 4.3、明天的日期
  350. /// 明天的日期
  351. static var tomorrowDate: Date? {
  352. return Calendar.current.date(byAdding: DateComponents(day: 1), to: Date())
  353. }
  354. // MARK: 4.4、前天的日期
  355. /// 前天的日期
  356. static var theDayBeforYesterDayDate: Date? {
  357. return Calendar.current.date(byAdding: DateComponents(day: -2), to: Date())
  358. }
  359. // MARK: 4.5、后天的日期
  360. /// 后天的日期
  361. static var theDayAfterYesterDayDate: Date? {
  362. return Calendar.current.date(byAdding: DateComponents(day: 2), to: Date())
  363. }
  364. // MARK: 4.6、是否为今天(只比较日期,不比较时分秒)
  365. /// 是否为今天(只比较日期,不比较时分秒)
  366. /// - Returns: bool
  367. var isToday: Bool {
  368. return Calendar.current.isDate(self, inSameDayAs: Date())
  369. }
  370. // MARK: 4.7、是否为昨天
  371. /// 是否为昨天
  372. var isYesterday: Bool {
  373. // 1.先拿到昨天的 date
  374. guard let date = Date.yesterDayDate else {
  375. return false
  376. }
  377. // 2.比较当前的日期和昨天的日期
  378. return Calendar.current.isDate(self, inSameDayAs: date)
  379. }
  380. // MARK: 4.8、是否为前天
  381. /// 是否为前天
  382. var isTheDayBeforeYesterday: Bool {
  383. // 1.先拿到前天的 date
  384. guard let date = Date.theDayBeforYesterDayDate else {
  385. return false
  386. }
  387. // 2.比较当前的日期和昨天的日期
  388. return Calendar.current.isDate(self, inSameDayAs: date)
  389. }
  390. // MARK: 4.9、是否为今年
  391. /// 是否为今年
  392. var isThisYear: Bool {
  393. let calendar = Calendar.current
  394. let nowCmps = calendar.dateComponents([.year], from: Date())
  395. let selfCmps = calendar.dateComponents([.year], from: self)
  396. let result = nowCmps.year == selfCmps.year
  397. return result
  398. }
  399. // MARK: 4.10、两个date是否为同一天
  400. /// 是否为 同一年 同一月 同一天
  401. /// - Returns: bool
  402. func isSameDay(date: Date) -> Bool {
  403. return Calendar.current.isDate(self, inSameDayAs: date)
  404. }
  405. // MARK: 4.11、当前日期是不是润年
  406. /// 当前日期是不是润年
  407. var isLeapYear: Bool {
  408. let year = self.year
  409. return ((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0)))
  410. }
  411. /// 日期的加减操作
  412. /// - Parameter day: 天数变化
  413. /// - Returns: date
  414. private func adding(day: Int) -> Date? {
  415. return Calendar.current.date(byAdding: DateComponents(day:day), to: self)
  416. }
  417. /// 是否为 同一年 同一月 同一天
  418. /// - Parameter date: date
  419. /// - Returns: 返回bool
  420. private func isSameYeaerMountDay(_ date: Date) -> Bool {
  421. let com = Calendar.current.dateComponents([.year, .month, .day], from: self)
  422. let comToday = Calendar.current.dateComponents([.year, .month, .day], from: date)
  423. return (com.day == comToday.day &&
  424. com.month == comToday.month &&
  425. com.year == comToday.year )
  426. }
  427. // MARK: 4.12、是否为本周
  428. /// 是否为本周
  429. /// - Returns: 是否为本周
  430. var isThisWeek: Bool {
  431. let calendar = Calendar.current
  432. // 当前时间
  433. let nowComponents = calendar.dateComponents([.weekday, .month, .year], from: Date())
  434. // self
  435. let selfComponents = calendar.dateComponents([.weekday,.month,.year], from: self as Date)
  436. return (selfComponents.year == nowComponents.year) && (selfComponents.month == nowComponents.month) && (selfComponents.weekday == nowComponents.weekday)
  437. }
  438. // MARK: 4.13、是否为12小时制
  439. /// 是否为12小时制
  440. /// - Returns: true:12小时,否则24小时
  441. static var isTwelve: Bool {
  442. var isTwelve: Bool = false
  443. if let formatString = DateFormatter.dateFormat(fromTemplate: "j", options: 0, locale: Locale.current), formatString.contains("a") {
  444. // 12 小时制
  445. isTwelve = true
  446. } else {
  447. // 24 小时制
  448. isTwelve = false
  449. }
  450. return isTwelve
  451. }
  452. }
  453. // MARK: - 五、相对的时间变化
  454. public extension Date {
  455. // MARK: 5.1、取得与当前时间的间隔差
  456. /// 取得与当前时间的间隔差
  457. /// - Returns: 时间差
  458. func callTimeAfterNow() -> String {
  459. let timeInterval = Date().timeIntervalSince(self)
  460. if timeInterval < 0 {
  461. return "刚刚"
  462. }
  463. let interval = fabs(timeInterval)
  464. let i60 = interval / 60
  465. let i3600 = interval / 3600
  466. let i86400 = interval / 86400
  467. let i2592000 = interval / 2592000
  468. let i31104000 = interval / 31104000
  469. var time:String!
  470. if i3600 < 1 {
  471. let s = NSNumber(value: i60 as Double).intValue
  472. if s == 0 {
  473. time = "刚刚"
  474. } else {
  475. time = "\(s)分钟前"
  476. }
  477. } else if i86400 < 1 {
  478. let s = NSNumber(value: i3600 as Double).intValue
  479. time = "\(s)小时前"
  480. } else if i2592000 < 1 {
  481. let s = NSNumber(value: i86400 as Double).intValue
  482. time = "\(s)天前"
  483. } else if i31104000 < 1 {
  484. let s = NSNumber(value: i2592000 as Double).intValue
  485. time = "\(s)个月前"
  486. } else {
  487. let s = NSNumber(value: i31104000 as Double).intValue
  488. time = "\(s)年前"
  489. }
  490. return time
  491. }
  492. // MARK: 5.2、获取两个日期之间的数据
  493. /// 获取两个日期之间的数据
  494. /// - Parameters:
  495. /// - date: 对比的日期
  496. /// - unit: 对比的类型
  497. /// - Returns: 两个日期之间的数据
  498. func componentCompare(from date: Date, unit: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute]) -> DateComponents {
  499. let calendar = Calendar.current
  500. let component = calendar.dateComponents(unit, from: date, to: self)
  501. return component
  502. }
  503. // MARK: 5.3、获取两个日期之间的天数
  504. /// 获取两个日期之间的天数
  505. /// - Parameter date: 对比的日期
  506. /// - Returns: 两个日期之间的天数
  507. func numberOfDays(from date: Date) -> Int? {
  508. return componentCompare(from: date, unit: [.day]).day
  509. }
  510. // MARK: 5.4、获取两个日期之间的小时
  511. /// 获取两个日期之间的小时
  512. /// - Parameter date: 对比的日期
  513. /// - Returns: 两个日期之间的小时
  514. func numberOfHours(from date: Date) -> Int? {
  515. return componentCompare(from: date, unit: [.hour]).hour
  516. }
  517. // MARK: 5.5、获取两个日期之间的分钟
  518. /// 获取两个日期之间的分钟
  519. /// - Parameter date: 对比的日期
  520. /// - Returns: 两个日期之间的分钟
  521. func numberOfMinutes(from date: Date) -> Int? {
  522. return componentCompare(from: date, unit: [.minute]).minute
  523. }
  524. // MARK: 5.6、获取两个日期之间的秒数
  525. /// 获取两个日期之间的秒数
  526. /// - Parameter date: 对比的日期
  527. /// - Returns: 两个日期之间的秒数
  528. func numberOfSeconds(from date: Date) -> Int? {
  529. return componentCompare(from: date, unit: [.second]).second
  530. }
  531. }
  532. // MARK: - 六、年/月/日 的一些判断
  533. public extension Date {
  534. // MARK: 6.1、获取当前的年
  535. /// 获取当前的年
  536. static var currentYear : Int {
  537. return currentDate.year
  538. }
  539. // MARK: 6.2、今年是不是闰年
  540. /// 1.16、今年是不是闰年
  541. static var currentYearIsLeapYear: Bool {
  542. return todayDate.isLeapYear
  543. }
  544. // MARK: 6.3、某年是不是闰年
  545. /// 6.3、某年是不是闰年
  546. static func yearIsLeapYear(year: Int) -> Bool {
  547. return ((year % 400 == 0) || ((year % 100 != 0) && (year % 4 == 0)))
  548. }
  549. // MARK: 6.4、当前的月份
  550. /// 当前的月份
  551. static var currentMonth: Int {
  552. return currentDate.month
  553. }
  554. // MARK: 6.5、获取当前月的天数
  555. /// 获取当前月的天数
  556. /// - Returns: 返回天数
  557. static var currentMonthDays: Int {
  558. return monthOfDays(month: currentMonth)
  559. }
  560. // MARK: 6.6、获取当前某月的天数
  561. /// 获取当前某月的天数
  562. /// - Returns: 返回天数
  563. static func monthOfDays(month: Int) -> Int {
  564. switch month {
  565. case 1, 3, 5, 7, 8, 10, 12:
  566. return 31
  567. case 4, 6, 9, 11:
  568. return 30
  569. case 2:
  570. return currentYearIsLeapYear ? 29 : 28
  571. default:
  572. fatalError("非法的月份:\(month)")
  573. }
  574. }
  575. }