From d0bc096b4a4b94cc62ce00541afb74860392df9c Mon Sep 17 00:00:00 2001 From: Thomas Van Lenten Date: Thu, 12 Jan 2017 17:13:10 -0500 Subject: Timestamp helper fix, Duration helper cleanup. - The Timestamp proto does not allow for negative nanos fields, so the seconds must be shifted and a positive nanos then applied. - Tweak the helpers on Duration to make it clear there is no "base" time involved. - Update the unittests for duration and timestamp to cover positive and negative NSTimeIntervals and what their impact is on the protos. --- objectivec/GPBWellKnownTypes.m | 52 ++++++++++++++++++++++++++++++------------ 1 file changed, 37 insertions(+), 15 deletions(-) (limited to 'objectivec/GPBWellKnownTypes.m') diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m index ed798a2e..2808afeb 100644 --- a/objectivec/GPBWellKnownTypes.m +++ b/objectivec/GPBWellKnownTypes.m @@ -41,15 +41,25 @@ NSString *const GPBWellKnownTypesErrorDomain = static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/"; -static NSTimeInterval TimeIntervalSince1970FromSecondsAndNanos(int64_t seconds, - int32_t nanos) { +static NSTimeInterval TimeIntervalFromSecondsAndNanos(int64_t seconds, + int32_t nanos) { return seconds + (NSTimeInterval)nanos / 1e9; } -static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time, - int64_t *outSeconds) { +static int32_t SecondsAndNanosFromTimeInterval(NSTimeInterval time, + int64_t *outSeconds, + BOOL nanosMustBePositive) { NSTimeInterval seconds; NSTimeInterval nanos = modf(time, &seconds); + + if (nanosMustBePositive && (nanos < 0)) { + // Per Timestamp.proto, nanos is non-negative and "Negative second values with + // fractions must still have non-negative nanos values that count forward in + // time. Must be from 0 to 999,999,999 inclusive." + --seconds; + nanos = 1.0 + nanos; + } + nanos *= 1e9; *outSeconds = (int64_t)seconds; return (int32_t)nanos; @@ -88,8 +98,8 @@ static NSString *ParseTypeFromURL(NSString *typeURLString) { - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { if ((self = [super init])) { int64_t seconds; - int32_t nanos = SecondsAndNanosFromTimeIntervalSince1970( - timeIntervalSince1970, &seconds); + int32_t nanos = SecondsAndNanosFromTimeInterval( + timeIntervalSince1970, &seconds, YES); self.seconds = seconds; self.nanos = nanos; } @@ -105,13 +115,13 @@ static NSString *ParseTypeFromURL(NSString *typeURLString) { } - (NSTimeInterval)timeIntervalSince1970 { - return TimeIntervalSince1970FromSecondsAndNanos(self.seconds, self.nanos); + return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); } - (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { int64_t seconds; int32_t nanos = - SecondsAndNanosFromTimeIntervalSince1970(timeIntervalSince1970, &seconds); + SecondsAndNanosFromTimeInterval(timeIntervalSince1970, &seconds, YES); self.seconds = seconds; self.nanos = nanos; } @@ -122,29 +132,41 @@ static NSString *ParseTypeFromURL(NSString *typeURLString) { @implementation GPBDuration (GBPWellKnownTypes) -- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { +- (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval { if ((self = [super init])) { int64_t seconds; - int32_t nanos = SecondsAndNanosFromTimeIntervalSince1970( - timeIntervalSince1970, &seconds); + int32_t nanos = SecondsAndNanosFromTimeInterval( + timeInterval, &seconds, NO); self.seconds = seconds; self.nanos = nanos; } return self; } -- (NSTimeInterval)timeIntervalSince1970 { - return TimeIntervalSince1970FromSecondsAndNanos(self.seconds, self.nanos); +- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + return [self initWithTimeInterval:timeIntervalSince1970]; } -- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { +- (NSTimeInterval)timeInterval { + return TimeIntervalFromSecondsAndNanos(self.seconds, self.nanos); +} + +- (void)setTimeInterval:(NSTimeInterval)timeInterval { int64_t seconds; int32_t nanos = - SecondsAndNanosFromTimeIntervalSince1970(timeIntervalSince1970, &seconds); + SecondsAndNanosFromTimeInterval(timeInterval, &seconds, NO); self.seconds = seconds; self.nanos = nanos; } +- (NSTimeInterval)timeIntervalSince1970 { + return self.timeInterval; +} + +- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 { + self.timeInterval = timeIntervalSince1970; +} + @end #pragma mark - GPBAny -- cgit v1.2.3