PageRenderTime 53ms CodeModel.GetById 18ms RepoModel.GetById 1ms app.codeStats 0ms

/AFDateHelper/AFDateExtension.swift

https://gitlab.com/praveenvelanati/AFDateHelper
Swift | 945 lines | 498 code | 108 blank | 339 comment | 52 complexity | 078ed84e27106e6e2ccb9bf4140e1304 MD5 | raw file
  1. //
  2. // AFDateExtension.swift
  3. //
  4. // Version 3.1.1
  5. //
  6. // Created by Melvin Rivera on 7/15/14.
  7. // Copyright (c) 2014. All rights reserved.
  8. //
  9. import Foundation
  10. // DotNet: "/Date(1268123281843)/"
  11. let DefaultFormat = "EEE MMM dd HH:mm:ss Z yyyy"
  12. let RSSFormat = "EEE, d MMM yyyy HH:mm:ss ZZZ" // "Fri, 09 Sep 2011 15:26:08 +0200"
  13. let AltRSSFormat = "d MMM yyyy HH:mm:ss ZZZ" // "09 Sep 2011 15:26:08 +0200"
  14. public enum ISO8601Format: String {
  15. case Year = "yyyy" // 1997
  16. case YearMonth = "yyyy-MM" // 1997-07
  17. case Date = "yyyy-MM-dd" // 1997-07-16
  18. case DateTime = "yyyy-MM-dd'T'HH:mmZ" // 1997-07-16T19:20+01:00
  19. case DateTimeSec = "yyyy-MM-dd'T'HH:mm:ssZ" // 1997-07-16T19:20:30+01:00
  20. case DateTimeMilliSec = "yyyy-MM-dd'T'HH:mm:ss.SSSZ" // 1997-07-16T19:20:30.45+01:00
  21. init(dateString:String) {
  22. switch dateString.characters.count {
  23. case 4:
  24. self = ISO8601Format(rawValue: ISO8601Format.Year.rawValue)!
  25. case 7:
  26. self = ISO8601Format(rawValue: ISO8601Format.YearMonth.rawValue)!
  27. case 10:
  28. self = ISO8601Format(rawValue: ISO8601Format.Date.rawValue)!
  29. case 22:
  30. self = ISO8601Format(rawValue: ISO8601Format.DateTime.rawValue)!
  31. case 25:
  32. self = ISO8601Format(rawValue: ISO8601Format.DateTimeSec.rawValue)!
  33. default:// 28:
  34. self = ISO8601Format(rawValue: ISO8601Format.DateTimeMilliSec.rawValue)!
  35. }
  36. }
  37. }
  38. public enum DateFormat {
  39. case ISO8601(ISO8601Format?), DotNet, RSS, AltRSS, Custom(String)
  40. }
  41. public extension NSDate {
  42. // MARK: Intervals In Seconds
  43. private class func minuteInSeconds() -> Double { return 60 }
  44. private class func hourInSeconds() -> Double { return 3600 }
  45. private class func dayInSeconds() -> Double { return 86400 }
  46. private class func weekInSeconds() -> Double { return 604800 }
  47. private class func yearInSeconds() -> Double { return 31556926 }
  48. // MARK: Components
  49. private class func componentFlags() -> NSCalendarUnit { return [NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Hour, NSCalendarUnit.Minute, NSCalendarUnit.Second, NSCalendarUnit.Weekday, NSCalendarUnit.WeekdayOrdinal, NSCalendarUnit.WeekOfYear] }
  50. private class func components(fromDate fromDate: NSDate) -> NSDateComponents! {
  51. return NSCalendar.currentCalendar().components(NSDate.componentFlags(), fromDate: fromDate)
  52. }
  53. private func components() -> NSDateComponents {
  54. return NSDate.components(fromDate: self)!
  55. }
  56. // MARK: Date From String
  57. /**
  58. Creates a date based on a string and a formatter type. You can ise .ISO8601(nil) to for deducting an ISO8601Format automatically.
  59. - Parameter fromString Date string i.e. "16 July 1972 6:12:00".
  60. - Parameter format The Date Formatter type can be .ISO8601(ISO8601Format?), .DotNet, .RSS, .AltRSS or Custom(String).
  61. - Returns A new date
  62. */
  63. convenience init(fromString string: String, format:DateFormat)
  64. {
  65. if string.isEmpty {
  66. self.init()
  67. return
  68. }
  69. let string = string as NSString
  70. switch format {
  71. case .DotNet:
  72. let startIndex = string.rangeOfString("(").location + 1
  73. let endIndex = string.rangeOfString(")").location
  74. let range = NSRange(location: startIndex, length: endIndex-startIndex)
  75. let milliseconds = (string.substringWithRange(range) as NSString).longLongValue
  76. let interval = NSTimeInterval(milliseconds / 1000)
  77. self.init(timeIntervalSince1970: interval)
  78. case .ISO8601(let isoFormat):
  79. let dateFormat = (isoFormat != nil) ? isoFormat! : ISO8601Format(dateString: string as String)
  80. let formatter = NSDate.formatter(format: dateFormat.rawValue)
  81. formatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
  82. formatter.timeZone = NSTimeZone.localTimeZone()
  83. formatter.dateFormat = dateFormat.rawValue
  84. if let date = formatter.dateFromString(string as String) {
  85. self.init(timeInterval:0, sinceDate:date)
  86. } else {
  87. self.init()
  88. }
  89. case .RSS:
  90. var s = string
  91. if string.hasSuffix("Z") {
  92. s = s.substringToIndex(s.length-1) + "GMT"
  93. }
  94. let formatter = NSDate.formatter(format: RSSFormat)
  95. if let date = formatter.dateFromString(string as String) {
  96. self.init(timeInterval:0, sinceDate:date)
  97. } else {
  98. self.init()
  99. }
  100. case .AltRSS:
  101. var s = string
  102. if string.hasSuffix("Z") {
  103. s = s.substringToIndex(s.length-1) + "GMT"
  104. }
  105. let formatter = NSDate.formatter(format: AltRSSFormat)
  106. if let date = formatter.dateFromString(string as String) {
  107. self.init(timeInterval:0, sinceDate:date)
  108. } else {
  109. self.init()
  110. }
  111. case .Custom(let dateFormat):
  112. let formatter = NSDate.formatter(format: dateFormat)
  113. if let date = formatter.dateFromString(string as String) {
  114. self.init(timeInterval:0, sinceDate:date)
  115. } else {
  116. self.init()
  117. }
  118. }
  119. }
  120. // MARK: Comparing Dates
  121. /**
  122. Returns true if dates are equal while ignoring time.
  123. - Parameter date: The Date to compare.
  124. */
  125. func isEqualToDateIgnoringTime(date: NSDate) -> Bool
  126. {
  127. let comp1 = NSDate.components(fromDate: self)
  128. let comp2 = NSDate.components(fromDate: date)
  129. return ((comp1.year == comp2.year) && (comp1.month == comp2.month) && (comp1.day == comp2.day))
  130. }
  131. /**
  132. Returns Returns true if date is today.
  133. */
  134. func isToday() -> Bool
  135. {
  136. return self.isEqualToDateIgnoringTime(NSDate())
  137. }
  138. /**
  139. Returns true if date is tomorrow.
  140. */
  141. func isTomorrow() -> Bool
  142. {
  143. return self.isEqualToDateIgnoringTime(NSDate().dateByAddingDays(1))
  144. }
  145. /**
  146. Returns true if date is yesterday.
  147. */
  148. func isYesterday() -> Bool
  149. {
  150. return self.isEqualToDateIgnoringTime(NSDate().dateBySubtractingDays(1))
  151. }
  152. /**
  153. Returns true if date are in the same week.
  154. - Parameter date: The date to compare.
  155. */
  156. func isSameWeekAsDate(date: NSDate) -> Bool
  157. {
  158. let comp1 = NSDate.components(fromDate: self)
  159. let comp2 = NSDate.components(fromDate: date)
  160. // Must be same week. 12/31 and 1/1 will both be week "1" if they are in the same week
  161. if comp1.weekOfYear != comp2.weekOfYear {
  162. return false
  163. }
  164. // Must have a time interval under 1 week
  165. return abs(self.timeIntervalSinceDate(date)) < NSDate.weekInSeconds()
  166. }
  167. /**
  168. Returns true if date is this week.
  169. */
  170. func isThisWeek() -> Bool
  171. {
  172. return self.isSameWeekAsDate(NSDate())
  173. }
  174. /**
  175. Returns true if date is next week.
  176. */
  177. func isNextWeek() -> Bool
  178. {
  179. let interval: NSTimeInterval = NSDate().timeIntervalSinceReferenceDate + NSDate.weekInSeconds()
  180. let date = NSDate(timeIntervalSinceReferenceDate: interval)
  181. return self.isSameWeekAsDate(date)
  182. }
  183. /**
  184. Returns true if date is last week.
  185. */
  186. func isLastWeek() -> Bool
  187. {
  188. let interval: NSTimeInterval = NSDate().timeIntervalSinceReferenceDate - NSDate.weekInSeconds()
  189. let date = NSDate(timeIntervalSinceReferenceDate: interval)
  190. return self.isSameWeekAsDate(date)
  191. }
  192. /**
  193. Returns true if dates are in the same year.
  194. - Parameter date: The date to compare.
  195. */
  196. func isSameYearAsDate(date: NSDate) -> Bool
  197. {
  198. let comp1 = NSDate.components(fromDate: self)
  199. let comp2 = NSDate.components(fromDate: date)
  200. return (comp1.year == comp2.year)
  201. }
  202. /**
  203. Returns true if date is this year.
  204. */
  205. func isThisYear() -> Bool
  206. {
  207. return self.isSameYearAsDate(NSDate())
  208. }
  209. /**
  210. Returns true if date is next year.
  211. */
  212. func isNextYear() -> Bool
  213. {
  214. let comp1 = NSDate.components(fromDate: self)
  215. let comp2 = NSDate.components(fromDate: NSDate())
  216. return (comp1.year == comp2.year + 1)
  217. }
  218. /**
  219. Returns true if date is last year.
  220. */
  221. func isLastYear() -> Bool
  222. {
  223. let comp1 = NSDate.components(fromDate: self)
  224. let comp2 = NSDate.components(fromDate: NSDate())
  225. return (comp1.year == comp2.year - 1)
  226. }
  227. /**
  228. Returns true if date is earlier than date.
  229. - Parameter date: The date to compare.
  230. */
  231. func isEarlierThanDate(date: NSDate) -> Bool
  232. {
  233. return self.earlierDate(date) == self
  234. }
  235. /**
  236. Returns true if date is later than date.
  237. - Parameter date: The date to compare.
  238. */
  239. func isLaterThanDate(date: NSDate) -> Bool
  240. {
  241. return self.laterDate(date) == self
  242. }
  243. /**
  244. Returns true if date is in future.
  245. */
  246. func isInFuture() -> Bool
  247. {
  248. return self.isLaterThanDate(NSDate())
  249. }
  250. /**
  251. Returns true if date is in past.
  252. */
  253. func isInPast() -> Bool
  254. {
  255. return self.isEarlierThanDate(NSDate())
  256. }
  257. // MARK: Adjusting Dates
  258. /**
  259. Creates a new date by a adding days.
  260. - Parameter days: The number of days to add.
  261. - Returns A new date object.
  262. */
  263. func dateByAddingDays(days: Int) -> NSDate
  264. {
  265. let dateComp = NSDateComponents()
  266. dateComp.day = days
  267. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  268. }
  269. /**
  270. Creates a new date by a substracting days.
  271. - Parameter days: The number of days to substract.
  272. - Returns A new date object.
  273. */
  274. func dateBySubtractingDays(days: Int) -> NSDate
  275. {
  276. let dateComp = NSDateComponents()
  277. dateComp.day = (days * -1)
  278. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  279. }
  280. /**
  281. Creates a new date by a adding hours.
  282. - Parameter days: The number of hours to add.
  283. - Returns A new date object.
  284. */
  285. func dateByAddingHours(hours: Int) -> NSDate
  286. {
  287. let dateComp = NSDateComponents()
  288. dateComp.hour = hours
  289. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  290. }
  291. /**
  292. Creates a new date by substracting hours.
  293. - Parameter days: The number of hours to substract.
  294. - Returns A new date object.
  295. */
  296. func dateBySubtractingHours(hours: Int) -> NSDate
  297. {
  298. let dateComp = NSDateComponents()
  299. dateComp.hour = (hours * -1)
  300. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  301. }
  302. /**
  303. Creates a new date by adding minutes.
  304. - Parameter days: The number of minutes to add.
  305. - Returns A new date object.
  306. */
  307. func dateByAddingMinutes(minutes: Int) -> NSDate
  308. {
  309. let dateComp = NSDateComponents()
  310. dateComp.minute = minutes
  311. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  312. }
  313. /**
  314. Creates a new date by substracting minutes.
  315. - Parameter days: The number of minutes to add.
  316. - Returns A new date object.
  317. */
  318. func dateBySubtractingMinutes(minutes: Int) -> NSDate
  319. {
  320. let dateComp = NSDateComponents()
  321. dateComp.minute = (minutes * -1)
  322. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  323. }
  324. /**
  325. Creates a new date by adding seconds.
  326. - Parameter seconds: The number of seconds to add.
  327. - Returns A new date object.
  328. */
  329. func dateByAddingSeconds(seconds: Int) -> NSDate
  330. {
  331. let dateComp = NSDateComponents()
  332. dateComp.second = seconds
  333. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  334. }
  335. /**
  336. Creates a new date by substracting seconds.
  337. - Parameter days: The number of seconds to substract.
  338. - Returns A new date object.
  339. */
  340. func dateBySubtractingSeconds(seconds: Int) -> NSDate
  341. {
  342. let dateComp = NSDateComponents()
  343. dateComp.second = (seconds * -1)
  344. return NSCalendar.currentCalendar().dateByAddingComponents(dateComp, toDate: self, options: NSCalendarOptions(rawValue: 0))!
  345. }
  346. /**
  347. Creates a new date from the start of the day.
  348. - Returns A new date object.
  349. */
  350. func dateAtStartOfDay() -> NSDate
  351. {
  352. let components = self.components()
  353. components.hour = 0
  354. components.minute = 0
  355. components.second = 0
  356. return NSCalendar.currentCalendar().dateFromComponents(components)!
  357. }
  358. /**
  359. Creates a new date from the end of the day.
  360. - Returns A new date object.
  361. */
  362. func dateAtEndOfDay() -> NSDate
  363. {
  364. let components = self.components()
  365. components.hour = 23
  366. components.minute = 59
  367. components.second = 59
  368. return NSCalendar.currentCalendar().dateFromComponents(components)!
  369. }
  370. /**
  371. Creates a new date from the start of the week.
  372. - Returns A new date object.
  373. */
  374. func dateAtStartOfWeek() -> NSDate
  375. {
  376. let flags :NSCalendarUnit = [NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Weekday]
  377. let components = NSCalendar.currentCalendar().components(flags, fromDate: self)
  378. components.weekday = NSCalendar.currentCalendar().firstWeekday
  379. components.hour = 0
  380. components.minute = 0
  381. components.second = 0
  382. return NSCalendar.currentCalendar().dateFromComponents(components)!
  383. }
  384. /**
  385. Creates a new date from the end of the week.
  386. - Returns A new date object.
  387. */
  388. func dateAtEndOfWeek() -> NSDate
  389. {
  390. let flags :NSCalendarUnit = [NSCalendarUnit.Year, NSCalendarUnit.Month, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Weekday]
  391. let components = NSCalendar.currentCalendar().components(flags, fromDate: self)
  392. components.weekday = NSCalendar.currentCalendar().firstWeekday + 6
  393. components.hour = 0
  394. components.minute = 0
  395. components.second = 0
  396. return NSCalendar.currentCalendar().dateFromComponents(components)!
  397. }
  398. /**
  399. Creates a new date from the first day of the month
  400. - Returns A new date object.
  401. */
  402. func dateAtTheStartOfMonth() -> NSDate
  403. {
  404. //Create the date components
  405. let components = self.components()
  406. components.day = 1
  407. //Builds the first day of the month
  408. let firstDayOfMonthDate :NSDate = NSCalendar.currentCalendar().dateFromComponents(components)!
  409. return firstDayOfMonthDate
  410. }
  411. /**
  412. Creates a new date from the last day of the month
  413. - Returns A new date object.
  414. */
  415. func dateAtTheEndOfMonth() -> NSDate {
  416. //Create the date components
  417. let components = self.components()
  418. //Set the last day of this month
  419. components.month += 1
  420. components.day = 0
  421. //Builds the first day of the month
  422. let lastDayOfMonth :NSDate = NSCalendar.currentCalendar().dateFromComponents(components)!
  423. return lastDayOfMonth
  424. }
  425. /**
  426. Creates a new date based on tomorrow.
  427. - Returns A new date object.
  428. */
  429. class func tomorrow() -> NSDate
  430. {
  431. return NSDate().dateByAddingDays(1).dateAtStartOfDay()
  432. }
  433. /**
  434. Creates a new date based on yesterdat.
  435. - Returns A new date object.
  436. */
  437. class func yesterday() -> NSDate
  438. {
  439. return NSDate().dateBySubtractingDays(1).dateAtStartOfDay()
  440. }
  441. // MARK: Retrieving Intervals
  442. /**
  443. Gets the number of seconds after a date.
  444. - Parameter date: the date to compare.
  445. - Returns The number of seconds
  446. */
  447. func secondsAfterDate(date: NSDate) -> Int
  448. {
  449. return Int(self.timeIntervalSinceDate(date))
  450. }
  451. /**
  452. Gets the number of seconds before a date.
  453. - Parameter date: The date to compare.
  454. - Returns The number of seconds
  455. */
  456. func secondsBeforeDate(date: NSDate) -> Int
  457. {
  458. return Int(date.timeIntervalSinceDate(self))
  459. }
  460. /**
  461. Gets the number of minutes after a date.
  462. - Parameter date: the date to compare.
  463. - Returns The number of minutes
  464. */
  465. func minutesAfterDate(date: NSDate) -> Int
  466. {
  467. let interval = self.timeIntervalSinceDate(date)
  468. return Int(interval / NSDate.minuteInSeconds())
  469. }
  470. /**
  471. Gets the number of minutes before a date.
  472. - Parameter date: The date to compare.
  473. - Returns The number of minutes
  474. */
  475. func minutesBeforeDate(date: NSDate) -> Int
  476. {
  477. let interval = date.timeIntervalSinceDate(self)
  478. return Int(interval / NSDate.minuteInSeconds())
  479. }
  480. /**
  481. Gets the number of hours after a date.
  482. - Parameter date: The date to compare.
  483. - Returns The number of hours
  484. */
  485. func hoursAfterDate(date: NSDate) -> Int
  486. {
  487. let interval = self.timeIntervalSinceDate(date)
  488. return Int(interval / NSDate.hourInSeconds())
  489. }
  490. /**
  491. Gets the number of hours before a date.
  492. - Parameter date: The date to compare.
  493. - Returns The number of hours
  494. */
  495. func hoursBeforeDate(date: NSDate) -> Int
  496. {
  497. let interval = date.timeIntervalSinceDate(self)
  498. return Int(interval / NSDate.hourInSeconds())
  499. }
  500. /**
  501. Gets the number of days after a date.
  502. - Parameter date: The date to compare.
  503. - Returns The number of days
  504. */
  505. func daysAfterDate(date: NSDate) -> Int
  506. {
  507. let interval = self.timeIntervalSinceDate(date)
  508. return Int(interval / NSDate.dayInSeconds())
  509. }
  510. /**
  511. Gets the number of days before a date.
  512. - Parameter date: The date to compare.
  513. - Returns The number of days
  514. */
  515. func daysBeforeDate(date: NSDate) -> Int
  516. {
  517. let interval = date.timeIntervalSinceDate(self)
  518. return Int(interval / NSDate.dayInSeconds())
  519. }
  520. // MARK: Decomposing Dates
  521. /**
  522. Returns the nearest hour.
  523. */
  524. func nearestHour () -> Int {
  525. let halfHour = NSDate.minuteInSeconds() * 30
  526. var interval = self.timeIntervalSinceReferenceDate
  527. if self.seconds() < 30 {
  528. interval -= halfHour
  529. } else {
  530. interval += halfHour
  531. }
  532. let date = NSDate(timeIntervalSinceReferenceDate: interval)
  533. return date.hour()
  534. }
  535. /**
  536. Returns the year component.
  537. */
  538. func year () -> Int { return self.components().year }
  539. /**
  540. Returns the month component.
  541. */
  542. func month () -> Int { return self.components().month }
  543. /**
  544. Returns the week of year component.
  545. */
  546. func week () -> Int { return self.components().weekOfYear }
  547. /**
  548. Returns the day component.
  549. */
  550. func day () -> Int { return self.components().day }
  551. /**
  552. Returns the hour component.
  553. */
  554. func hour () -> Int { return self.components().hour }
  555. /**
  556. Returns the minute component.
  557. */
  558. func minute () -> Int { return self.components().minute }
  559. /**
  560. Returns the seconds component.
  561. */
  562. func seconds () -> Int { return self.components().second }
  563. /**
  564. Returns the weekday component.
  565. */
  566. func weekday () -> Int { return self.components().weekday }
  567. /**
  568. Returns the nth days component. e.g. 2nd Tuesday of the month is 2.
  569. */
  570. func nthWeekday () -> Int { return self.components().weekdayOrdinal }
  571. /**
  572. Returns the days of the month.
  573. */
  574. func monthDays () -> Int { return NSCalendar.currentCalendar().rangeOfUnit(NSCalendarUnit.Day, inUnit: NSCalendarUnit.Month, forDate: self).length }
  575. /**
  576. Returns the first day of the week.
  577. */
  578. func firstDayOfWeek () -> Int {
  579. let distanceToStartOfWeek = NSDate.dayInSeconds() * Double(self.components().weekday - 1)
  580. let interval: NSTimeInterval = self.timeIntervalSinceReferenceDate - distanceToStartOfWeek
  581. return NSDate(timeIntervalSinceReferenceDate: interval).day()
  582. }
  583. /**
  584. Returns the last day of the week.
  585. */
  586. func lastDayOfWeek () -> Int {
  587. let distanceToStartOfWeek = NSDate.dayInSeconds() * Double(self.components().weekday - 1)
  588. let distanceToEndOfWeek = NSDate.dayInSeconds() * Double(7)
  589. let interval: NSTimeInterval = self.timeIntervalSinceReferenceDate - distanceToStartOfWeek + distanceToEndOfWeek
  590. return NSDate(timeIntervalSinceReferenceDate: interval).day()
  591. }
  592. /**
  593. Returns true if a weekday.
  594. */
  595. func isWeekday() -> Bool {
  596. return !self.isWeekend()
  597. }
  598. /**
  599. Returns true if weekend.
  600. */
  601. func isWeekend() -> Bool {
  602. let range = NSCalendar.currentCalendar().maximumRangeOfUnit(NSCalendarUnit.Weekday)
  603. return (self.weekday() == range.location || self.weekday() == range.length)
  604. }
  605. // MARK: To String
  606. /**
  607. A string representation using short date and time style.
  608. */
  609. func toString() -> String {
  610. return self.toString(dateStyle: .ShortStyle, timeStyle: .ShortStyle, doesRelativeDateFormatting: false)
  611. }
  612. /**
  613. A string representation based on a format.
  614. - Parameter format: The format of date can be .ISO8601(.ISO8601Format?), .DotNet, .RSS, .AltRSS or Custom(FormatString).
  615. - Returns The date string representation
  616. */
  617. func toString(format format: DateFormat) -> String
  618. {
  619. var dateFormat: String
  620. switch format {
  621. case .DotNet:
  622. let offset = NSTimeZone.defaultTimeZone().secondsFromGMT / 3600
  623. let nowMillis = 1000 * self.timeIntervalSince1970
  624. return "/Date(\(nowMillis)\(offset))/"
  625. case .ISO8601(let isoFormat):
  626. dateFormat = (isoFormat != nil) ? isoFormat!.rawValue : ISO8601Format.DateTimeMilliSec.rawValue
  627. case .RSS:
  628. dateFormat = RSSFormat
  629. case .AltRSS:
  630. dateFormat = AltRSSFormat
  631. case .Custom(let string):
  632. dateFormat = string
  633. }
  634. let formatter = NSDate.formatter(format: dateFormat)
  635. return formatter.stringFromDate(self)
  636. }
  637. /**
  638. A string representation based on custom style.
  639. - Parameter dateStyle: The date style to use.
  640. - Parameter timeStyle: The time style to use.
  641. - Parameter doesRelativeDateFormatting: Enables relative date formatting.
  642. - Returns A string representation of the date.
  643. */
  644. func toString(dateStyle dateStyle: NSDateFormatterStyle, timeStyle: NSDateFormatterStyle, doesRelativeDateFormatting: Bool = false) -> String
  645. {
  646. let formatter = NSDate.formatter(dateStyle: dateStyle, timeStyle: timeStyle, doesRelativeDateFormatting: doesRelativeDateFormatting)
  647. return formatter.stringFromDate(self)
  648. }
  649. /**
  650. A string representation based on a relative time language. i.e. just now, 1 minute ago etc..
  651. */
  652. func relativeTimeToString() -> String
  653. {
  654. let time = self.timeIntervalSince1970
  655. let now = NSDate().timeIntervalSince1970
  656. let seconds = now - time
  657. let minutes = round(seconds/60)
  658. let hours = round(minutes/60)
  659. let days = round(hours/24)
  660. if seconds < 10 {
  661. return NSLocalizedString("just now", comment: "Show the relative time from a date")
  662. } else if seconds < 60 {
  663. let relativeTime = NSLocalizedString("%.f seconds ago", comment: "Show the relative time from a date")
  664. return String(format: relativeTime, seconds)
  665. }
  666. if minutes < 60 {
  667. if minutes == 1 {
  668. return NSLocalizedString("1 minute ago", comment: "Show the relative time from a date")
  669. } else {
  670. let relativeTime = NSLocalizedString("%.f minutes ago", comment: "Show the relative time from a date")
  671. return String(format: relativeTime, minutes)
  672. }
  673. }
  674. if hours < 24 {
  675. if hours == 1 {
  676. return NSLocalizedString("1 hour ago", comment: "Show the relative time from a date")
  677. } else {
  678. let relativeTime = NSLocalizedString("%.f hours ago", comment: "Show the relative time from a date")
  679. return String(format: relativeTime, hours)
  680. }
  681. }
  682. if days < 7 {
  683. if days == 1 {
  684. return NSLocalizedString("1 day ago", comment: "Show the relative time from a date")
  685. } else {
  686. let relativeTime = NSLocalizedString("%.f days ago", comment: "Show the relative time from a date")
  687. return String(format: relativeTime, days)
  688. }
  689. }
  690. return self.toString()
  691. }
  692. /**
  693. A string representation of the weekday.
  694. */
  695. func weekdayToString() -> String {
  696. let formatter = NSDate.formatter()
  697. return formatter.weekdaySymbols[self.weekday()-1] as String
  698. }
  699. /**
  700. A short string representation of the weekday.
  701. */
  702. func shortWeekdayToString() -> String {
  703. let formatter = NSDate.formatter()
  704. return formatter.shortWeekdaySymbols[self.weekday()-1] as String
  705. }
  706. /**
  707. A very short string representation of the weekday.
  708. - Returns String
  709. */
  710. func veryShortWeekdayToString() -> String {
  711. let formatter = NSDate.formatter()
  712. return formatter.veryShortWeekdaySymbols[self.weekday()-1] as String
  713. }
  714. /**
  715. A string representation of the month.
  716. - Returns String
  717. */
  718. func monthToString() -> String {
  719. let formatter = NSDate.formatter()
  720. return formatter.monthSymbols[self.month()-1] as String
  721. }
  722. /**
  723. A short string representation of the month.
  724. - Returns String
  725. */
  726. func shortMonthToString() -> String {
  727. let formatter = NSDate.formatter()
  728. return formatter.shortMonthSymbols[self.month()-1] as String
  729. }
  730. /**
  731. A very short string representation of the month.
  732. - Returns String
  733. */
  734. func veryShortMonthToString() -> String {
  735. let formatter = NSDate.formatter()
  736. return formatter.veryShortMonthSymbols[self.month()-1] as String
  737. }
  738. // MARK: Static Cached Formatters
  739. /**
  740. Returns a cached static array of NSDateFormatters so that thy are only created once.
  741. */
  742. private class func sharedDateFormatters() -> [String: NSDateFormatter] {
  743. struct Static {
  744. static var formatters: [String: NSDateFormatter]? = nil
  745. static var once: dispatch_once_t = 0
  746. }
  747. dispatch_once(&Static.once) {
  748. Static.formatters = [String: NSDateFormatter]()
  749. }
  750. return Static.formatters!
  751. }
  752. /**
  753. Returns a cached formatter based on the format, timeZone and locale. Formatters are cached in a singleton array using hashkeys generated by format, timeZone and locale.
  754. - Parameter format: The format to use.
  755. - Parameter timeZone: The time zone to use, defaults to the local time zone.
  756. - Parameter locale: The locale to use, defaults to the current locale
  757. - Returns The date formatter.
  758. */
  759. private class func formatter(format format:String = DefaultFormat, timeZone: NSTimeZone = NSTimeZone.localTimeZone(), locale: NSLocale = NSLocale.currentLocale()) -> NSDateFormatter {
  760. let hashKey = "\(format.hashValue)\(timeZone.hashValue)\(locale.hashValue)"
  761. var formatters = NSDate.sharedDateFormatters()
  762. if let cachedDateFormatter = formatters[hashKey] {
  763. return cachedDateFormatter
  764. } else {
  765. let formatter = NSDateFormatter()
  766. formatter.dateFormat = format
  767. formatter.timeZone = timeZone
  768. formatter.locale = locale
  769. formatters[hashKey] = formatter
  770. return formatter
  771. }
  772. }
  773. /**
  774. Returns a cached formatter based on date style, time style and relative date. Formatters are cached in a singleton array using hashkeys generated by date style, time style, relative date, timeZone and locale.
  775. - Parameter dateStyle: The date style to use.
  776. - Parameter timeStyle: The time style to use.
  777. - Parameter doesRelativeDateFormatting: Enables relative date formatting.
  778. - Parameter timeZone: The time zone to use.
  779. - Parameter locale: The locale to use.
  780. - Returns The date formatter.
  781. */
  782. private class func formatter(dateStyle dateStyle: NSDateFormatterStyle, timeStyle: NSDateFormatterStyle, doesRelativeDateFormatting: Bool, timeZone: NSTimeZone = NSTimeZone.localTimeZone(), locale: NSLocale = NSLocale.currentLocale()) -> NSDateFormatter {
  783. var formatters = NSDate.sharedDateFormatters()
  784. let hashKey = "\(dateStyle.hashValue)\(timeStyle.hashValue)\(doesRelativeDateFormatting.hashValue)\(timeZone.hashValue)\(locale.hashValue)"
  785. if let cachedDateFormatter = formatters[hashKey] {
  786. return cachedDateFormatter
  787. } else {
  788. let formatter = NSDateFormatter()
  789. formatter.dateStyle = dateStyle
  790. formatter.timeStyle = timeStyle
  791. formatter.doesRelativeDateFormatting = doesRelativeDateFormatting
  792. formatter.timeZone = timeZone
  793. formatter.locale = locale
  794. formatters[hashKey] = formatter
  795. return formatter
  796. }
  797. }
  798. }