TimeUtils.swift 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566
  1. // Sources/SwiftProtobuf/TimeUtils.swift - Generally useful time/calendar functions
  2. //
  3. // Copyright (c) 2014 - 2017 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. ///
  11. /// Generally useful time/calendar functions and constants
  12. ///
  13. // -----------------------------------------------------------------------------
  14. let minutesPerDay: Int32 = 1440
  15. let minutesPerHour: Int32 = 60
  16. let secondsPerDay: Int32 = 86400
  17. let secondsPerHour: Int32 = 3600
  18. let secondsPerMinute: Int32 = 60
  19. let nanosPerSecond: Int32 = 1_000_000_000
  20. let attosPerNanosecond: Int64 = 1_000_000_000
  21. internal func timeOfDayFromSecondsSince1970(seconds: Int64) -> (hh: Int32, mm: Int32, ss: Int32) {
  22. let secondsSinceMidnight = Int32(mod(seconds, Int64(secondsPerDay)))
  23. let ss = mod(secondsSinceMidnight, secondsPerMinute)
  24. let mm = mod(div(secondsSinceMidnight, secondsPerMinute), minutesPerHour)
  25. let hh = Int32(div(secondsSinceMidnight, secondsPerHour))
  26. return (hh: hh, mm: mm, ss: ss)
  27. }
  28. internal func julianDayNumberFromSecondsSince1970(seconds: Int64) -> Int64 {
  29. // January 1, 1970 is Julian Day Number 2440588.
  30. // See http://aa.usno.navy.mil/faq/docs/JD_Formula.php
  31. div(seconds + 2_440_588 * Int64(secondsPerDay), Int64(secondsPerDay))
  32. }
  33. internal func gregorianDateFromSecondsSince1970(seconds: Int64) -> (YY: Int32, MM: Int32, DD: Int32) {
  34. // The following implements Richards' algorithm (see the Wikipedia article
  35. // for "Julian day").
  36. // If you touch this code, please test it exhaustively by playing with
  37. // Test_Timestamp.testJSON_range.
  38. let JJ = julianDayNumberFromSecondsSince1970(seconds: seconds)
  39. let f = JJ + 1401 + div(div(4 * JJ + 274277, 146097) * 3, 4) - 38
  40. let e = 4 * f + 3
  41. let g = Int64(div(mod(e, 1461), 4))
  42. let h = 5 * g + 2
  43. let DD = div(mod(h, 153), 5) + 1
  44. let MM = mod(div(h, 153) + 2, 12) + 1
  45. let YY = div(e, 1461) - 4716 + div(12 + 2 - MM, 12)
  46. return (YY: Int32(YY), MM: Int32(MM), DD: Int32(DD))
  47. }
  48. internal func nanosToString(nanos: Int32) -> String {
  49. if nanos == 0 {
  50. return ""
  51. } else if nanos % 1_000_000 == 0 {
  52. return ".\(threeDigit(abs(nanos) / 1_000_000))"
  53. } else if nanos % 1000 == 0 {
  54. return ".\(sixDigit(abs(nanos) / 1000))"
  55. } else {
  56. return ".\(nineDigit(abs(nanos)))"
  57. }
  58. }