diff --git a/Sources/MessagePackExtension.swift b/Sources/MessagePackExtension.swift index a5a6939..f6154ab 100644 --- a/Sources/MessagePackExtension.swift +++ b/Sources/MessagePackExtension.swift @@ -28,7 +28,19 @@ extension MessagePackExtension { case let (0, value): self.data = packInteger(for: value.bigEndian) default: - self.data = packInteger(for: UInt32(timestamp.nanoseconds).bigEndian) + packInteger(for: Int64(timestamp.seconds).bigEndian) + if timestamp.nanoseconds < 0 { + // Adjust these values from + // "negative nanosec from nearest larger negative integer" + // to + // "positive nanosec from nearest smaller nagative integer". + let seconds = timestamp.seconds - 1 + let nanoSeconds = (MessagePackTimestamp.NSEC_MAX + 1) + timestamp.nanoseconds + self.data = packInteger(for: UInt32(nanoSeconds).bigEndian) + packInteger(for: Int64(seconds).bigEndian) + } + else { + self.data = packInteger(for: UInt32(timestamp.nanoseconds).bigEndian) + packInteger(for: Int64(timestamp.seconds).bigEndian) + } + } } } diff --git a/Sources/MessagePackTimestamp.swift b/Sources/MessagePackTimestamp.swift index 94f2e7b..e62a5ce 100644 --- a/Sources/MessagePackTimestamp.swift +++ b/Sources/MessagePackTimestamp.swift @@ -9,6 +9,7 @@ import Foundation public struct MessagePackTimestamp: Equatable { + internal static let NSEC_MAX: Int64 = 999999999 public var seconds: Int64 public var nanoseconds: Int64 diff --git a/Tests/MessagePackerTests/TimestampPackedTests.swift b/Tests/MessagePackerTests/TimestampPackedTests.swift index cd60305..e895aea 100644 --- a/Tests/MessagePackerTests/TimestampPackedTests.swift +++ b/Tests/MessagePackerTests/TimestampPackedTests.swift @@ -37,4 +37,17 @@ class TimestampPackedTests: XCTestCase { let output = Data([199, 12, 255, 25, 69, 229, 222, 0, 0, 0, 14, 211, 132, 20, 74]) XCTAssertEqual(try encoder.encode(input), output) } + + func testTimestamp96WithNegativeDate() throws { + let formatter = DateFormatter() + formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" + formatter.locale = Locale(identifier: "en_US_POSIX") + formatter.timeZone = TimeZone(abbreviation: "UTC") + let date = formatter.date(from: "0023-09-24T00:36:30.078Z")! + + let timestamp = MessagePackTimestamp(date: date) + let encoded = try encoder.encode(timestamp) + let decoded = try MessagePackDecoder().decode(MessagePackTimestamp.self, from: encoded) + XCTAssertEqual(date, Date(timestamp: decoded)) + } }