如何将 unix 时间戳转换为 NSData 对象?

How to convert unix timestamp to NSData object?

我正在使用 Core Bluetooth 写入外围设备。我想将当前的 unix 时间戳发送到传感器,我尝试这样做:

// Write timestamp to paired peripheral
NSDate*           measureTime = [NSDate date];
NSDateFormatter*  usDateFormatter = [NSDateFormatter new];
NSLocale*         enUSPOSIXLocale = [[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"];

[usDateFormatter setDateFormat:@"yyyy-MM-dd'T'HH:mm:ss.000'Z'"];
[usDateFormatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"UTC"]];
[usDateFormatter setLocale:enUSPOSIXLocale];  // Should force 24hr time regardless of settings value

NSString *dateString = [usDateFormatter stringFromDate:measureTime];
NSDate* startTime = [usDateFormatter dateFromString:dateString];

uint32_t timestamp = [startTime timeIntervalSince1970];
NSData *timestampData = [NSData dataWithBytes:&timestamp length:sizeof(timestamp)]; // <- Troublemaker
[pairedPeripheral writeValue:timestampData forCharacteristic:currentCharacteristic type:CBCharacteristicWriteWithResponse];

这是问题所在:

我的 32 位时间戳 returns 是正确的值,但是当我将它转换为 NSData 时,外围设备将其读取为 24 小时时钟值,如下所示:“16:42:96”

我哪里出错了?

编辑

我修改了代码以摆脱 NSDateFormatter,因为有人提到这是不必要的。我似乎仍然得到相同的结果:

// Write timestamp to paired peripheral
NSDate*           measureTime = [NSDate date];
uint64_t timestamp = [measureTime timeIntervalSince1970];
NSData *timestampData = [NSData dataWithBytes:&timestamp length:sizeof(timestamp)]; // <- Troublemaker
[pairedPeripheral writeValue:timestampData forCharacteristic:currentCharacteristic type:CBCharacteristicWriteWithResponse]; 

没有必要使用 NSDateFormatter,除非您打算向外围设备发送字符串表示形式。

来自Apple Developer docs

NSDate objects encapsulate a single point in time, independent of any particular calendrical system or time zone. Date objects are immutable, representing an invariant time interval relative to an absolute reference date (00:00:00 UTC on 1 January 2001).

考虑到这一点,您可以按原样使用 measureTime,并获得相同的结果:

uint32_t timestamp = [measureTime timeIntervalSince1970];

在不了解外围设备具体情况的情况下,无法说明它为什么显示 24 小时值。

如果我敢猜测,我希望您首先需要修改另一个特征/值,以便将其切换为不同的格式(如果可能的话)。

你糊涂了。您发送给外围设备的是自 1970 年以来的整数秒数。这是发送 Unix 时间戳的合理方式,但它不是 24 小时格式的时间,它是一个整数。

您将需要更改您的代码以使用 uint64_t 或 uint32_t,因为 Unix 时间戳是比 32 位整数大得多的数字。 (我建议使用 uint64_t。)

(请参阅@DonMag 的评论以了解示例时间戳值,例如 1491580283)

当外设接收到时间后如何显示是一个单独的问题,也是您真正应该问的问题。

请注意,如果外围设备 "endian-ness" 与您的 iOS 设备不同,您可能 运行 会遇到将 int 作为二进制数据发送的问题。您可能希望将时间戳整数转换为字符串并发送它以避免字节顺序问题。