RFC1123DateFormatter.swift 3.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. // Borrowed from Vapor (Date Middleware)
  2. // https://github.com/vapor/vapor/blob/master/Sources/Vapor/Middleware/DateMiddleware.swift
  3. import Foundation
  4. #if os(Linux)
  5. import Glibc
  6. #else
  7. import Darwin.C
  8. #endif
  9. fileprivate let DAY_NAMES = [
  10. "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
  11. ]
  12. fileprivate let MONTH_NAMES = [
  13. "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
  14. ]
  15. fileprivate let NUMBERS = [
  16. "00", "01", "02", "03", "04", "05", "06", "07", "08", "09",
  17. "10", "11", "12", "13", "14", "15", "16", "17", "18", "19",
  18. "20", "21", "22", "23", "24", "25", "26", "27", "28", "29",
  19. "30", "31", "32", "33", "34", "35", "36", "37", "38", "39",
  20. "40", "41", "42", "43", "44", "45", "46", "47", "48", "49",
  21. "50", "51", "52", "53", "54", "55", "56", "57", "58", "59",
  22. "60", "61", "62", "63", "64", "65", "66", "67", "68", "69",
  23. "70", "71", "72", "73", "74", "75", "76", "77", "78", "79",
  24. "80", "81", "82", "83", "84", "85", "86", "87", "88", "89",
  25. "90", "91", "92", "93", "94", "95", "96", "97", "98", "99"
  26. ]
  27. fileprivate var cachedTimeComponents: (key: time_t, components: tm)?
  28. let secondsInDay = 60 * 60 * 24
  29. let accuracy = 1 // seconds
  30. final class RFC1123DateFormatter {
  31. var cachedTimestamp: (timestamp: String, createdAt: time_t)?
  32. /// Gets the current RFC 1123 date string.
  33. func getDate() -> String {
  34. var date = time(nil)
  35. if let (timestamp, createdAt) = cachedTimestamp, (createdAt...(createdAt + accuracy)).contains(date) {
  36. return timestamp
  37. }
  38. // generate a key used for caching.
  39. // this key is a unique id for each day
  40. let key = date / secondsInDay
  41. // get time components
  42. let dateComponents: tm
  43. if let cached = cachedTimeComponents, cached.key == key {
  44. dateComponents = cached.components
  45. } else {
  46. let tc = gmtime(&date).pointee
  47. dateComponents = tc
  48. cachedTimeComponents = (key: key, components: tc)
  49. }
  50. // parse components
  51. let year: Int = numericCast(dateComponents.tm_year) + 1900 // years since 1900
  52. let month: Int = numericCast(dateComponents.tm_mon) // months since January [0-11]
  53. let monthDay: Int = numericCast(dateComponents.tm_mday) // day of the month [1-31]
  54. let weekDay: Int = numericCast(dateComponents.tm_wday) // days since Sunday [0-6]
  55. // get basic time info
  56. let timeX: Int = date % secondsInDay
  57. let hours: Int = numericCast(timeX / 3600)
  58. let minutes: Int = numericCast((timeX / 60) % 60)
  59. let seconds: Int = numericCast(timeX % 60)
  60. var rfc1123 = ""
  61. rfc1123.reserveCapacity(30)
  62. rfc1123.append(DAY_NAMES[weekDay])
  63. rfc1123.append(", ")
  64. rfc1123.append(NUMBERS[monthDay])
  65. rfc1123.append(" ")
  66. rfc1123.append(MONTH_NAMES[month])
  67. rfc1123.append(" ")
  68. rfc1123.append(NUMBERS[year / 100])
  69. rfc1123.append(NUMBERS[year % 100])
  70. rfc1123.append(" ")
  71. rfc1123.append(NUMBERS[hours])
  72. rfc1123.append(":")
  73. rfc1123.append(NUMBERS[minutes])
  74. rfc1123.append(":")
  75. rfc1123.append(NUMBERS[seconds])
  76. rfc1123.append(" GMT")
  77. cachedTimestamp = (rfc1123, date)
  78. return rfc1123
  79. }
  80. }