Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Merge pull request #143 from libgit2/date-fixes

Date fixes
  • Loading branch information...
commit 51df316ab23b314faae1f5c2d9d7a4ea9344f5ed 2 parents 3e69046 + d77bd3f
@joshaber joshaber authored
View
41 Classes/Categories/NSDate+GTTimeAdditions.h
@@ -0,0 +1,41 @@
+//
+// NSDate+GTTimeAdditions.h
+// ObjectiveGitFramework
+//
+// Created by Danny Greg on 27/03/2013.
+// Copyright (c) 2013 GitHub, Inc. All rights reserved.
+//
+
+#import <Foundation/Foundation.h>
+
+#import "git2.h"
+
+@interface NSDate (GTTimeAdditions)
+
+// Creates a new `NSDate` from the provided `git_time`.
+//
+// time - The `git_time` to base the returned date on.
+//
+// Returns an `NSDate` object representing the passed in `time`.
++ (NSDate *)gt_dateFromGitTime:(git_time)time;
+
+// Converts the date to a `git_time`.
+//
+// timeZone - An `NSTimeZone` to describe the time offset. This is optional, if
+// `nil` the default time zone will be used.
+- (git_time)gt_gitTimeUsingTimeZone:(NSTimeZone *)timeZone;
+
+@end
+
+@interface NSTimeZone (GTTimeAdditions)
+
+// Creates a new `NSTimeZone` from the provided `git_time`.
+//
+// Returns an `NSTimeZone` object representing the time zone for the offset in
+// the passed in `git_time`.
++ (NSTimeZone *)gt_timeZoneFromGitTime:(git_time)time;
+
+// The difference, in minutes, between the current default timezone and GMT.
+@property (nonatomic, readonly) int gt_gitTimeOffset;
+
+@end
View
36 Classes/Categories/NSDate+GTTimeAdditions.m
@@ -0,0 +1,36 @@
+//
+// NSDate+GTTimeAdditions.m
+// ObjectiveGitFramework
+//
+// Created by Danny Greg on 27/03/2013.
+// Copyright (c) 2013 GitHub, Inc. All rights reserved.
+//
+
+#import "NSDate+GTTimeAdditions.h"
+
+@implementation NSDate (GTTimeAdditions)
+
++ (NSDate *)gt_dateFromGitTime:(git_time)time {
+ return [NSDate dateWithTimeIntervalSince1970:time.time];
+}
+
+- (git_time)gt_gitTimeUsingTimeZone:(NSTimeZone *)timeZone {
+ NSTimeZone *correctedTimeZone = timeZone ?: NSTimeZone.defaultTimeZone;
+ return (git_time){ .offset = correctedTimeZone.gt_gitTimeOffset, .time = (git_time_t)self.timeIntervalSince1970 };
+}
+
+@end
+
+@implementation NSTimeZone (GTTimeAdditions)
+
++ (NSTimeZone *)gt_timeZoneFromGitTime:(git_time)time {
+ return [NSTimeZone timeZoneForSecondsFromGMT:time.offset * 60];
+}
+
+- (int)gt_gitTimeOffset {
+ NSInteger timezoneOffset = self.secondsFromGMT;
+ int offset = (int)timezoneOffset / 60;
+ return offset;
+}
+
+@end
View
1  Classes/GTCommit.h
@@ -44,6 +44,7 @@
@property (nonatomic, readonly) NSString *messageDetails;
@property (nonatomic, readonly) NSString *messageSummary;
@property (nonatomic, readonly) NSDate *commitDate;
+@property (nonatomic, readonly) NSTimeZone *commitTimeZone;
@property (nonatomic, readonly) GTTree *tree;
+ (GTCommit *)commitInRepository:(GTRepository *)theRepo updateRefNamed:(NSString *)refName author:(GTSignature *)authorSig committer:(GTSignature *)committerSig message:(NSString *)newMessage tree:(GTTree *)theTree parents:(NSArray *)theParents error:(NSError **)error;
View
12 Classes/GTCommit.m
@@ -33,6 +33,7 @@
#import "NSError+Git.h"
#import "GTRepository.h"
#import "NSString+Git.h"
+#import "NSDate+GTTimeAdditions.h"
@interface GTCommit ()
@property (nonatomic, strong) GTSignature *author;
@@ -119,9 +120,16 @@ - (NSString *)messageSummary {
return messageComponents.count > 0 ? [messageComponents objectAtIndex:0] : @"";
}
+- (git_time)commitTime {
+ return (git_time){ .time = git_commit_time(self.git_commit), .offset = git_commit_time_offset(self.git_commit) };
+}
+
- (NSDate *)commitDate {
- time_t t = git_commit_time(self.git_commit);
- return [NSDate dateWithTimeIntervalSince1970:t];
+ return [NSDate gt_dateFromGitTime:self.commitTime];
+}
+
+- (NSTimeZone *)commitTimeZone {
+ return [NSTimeZone gt_timeZoneFromGitTime:self.commitTime];
}
- (GTSignature *)author {
View
1  Classes/GTSignature.h
@@ -37,6 +37,7 @@
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *email;
@property (nonatomic, strong) NSDate *time;
+@property (nonatomic, readonly, copy) NSTimeZone *timeZone;
// Convenience initializers
- (id)initWithSignature:(git_signature *)theSignature;
View
18 Classes/GTSignature.m
@@ -29,6 +29,7 @@
#import "GTSignature.h"
+#import "NSDate+GTTimeAdditions.h"
@implementation GTSignature
@@ -61,8 +62,8 @@ - (id)initWithSignature:(git_signature *)theSignature {
- (id)initWithName:(NSString *)theName email:(NSString *)theEmail time:(NSDate *)theTime {
if((self = [super init])) {
- git_signature_new(&git_signature, [theName UTF8String], [theEmail UTF8String], (git_time_t) [theTime timeIntervalSince1970], 0);
- // todo: figure out offset for NSDate
+ git_time gitTime = [theTime gt_gitTimeUsingTimeZone:nil];
+ git_signature_new(&git_signature, theName.UTF8String, theEmail.UTF8String, gitTime.time, gitTime.offset);
}
return self;
}
@@ -85,12 +86,17 @@ - (void)setEmail:(NSString *)e {
self.git_signature->email = strdup([e cStringUsingEncoding:NSUTF8StringEncoding]);
}
-- (NSDate *)time {
- return [NSDate dateWithTimeIntervalSince1970:self.git_signature->when.time];
+- (NSDate *)time {
+ return [NSDate gt_dateFromGitTime:self.git_signature->when];
}
-- (void)setTime:(NSDate *)d {
- self.git_signature->when.time = (git_time_t) [d timeIntervalSince1970];
+- (NSTimeZone *)timeZone {
+ return [NSTimeZone gt_timeZoneFromGitTime:self.git_signature->when];
+}
+
+- (void)setTime:(NSDate *)date {
+ git_time newTime = [date gt_gitTimeUsingTimeZone:nil];
+ self.git_signature->when = newTime;
}
@end
View
16 ObjectiveGitFramework.xcodeproj/project.pbxproj
@@ -79,6 +79,11 @@
30A3D6551667F11C00C49A39 /* GTDiff.h in Headers */ = {isa = PBXBuildFile; fileRef = 30A3D6521667F11C00C49A39 /* GTDiff.h */; settings = {ATTRIBUTES = (Public, ); }; };
30A3D6561667F11C00C49A39 /* GTDiff.m in Sources */ = {isa = PBXBuildFile; fileRef = 30A3D6531667F11C00C49A39 /* GTDiff.m */; };
30A3D6571667F11C00C49A39 /* GTDiff.m in Sources */ = {isa = PBXBuildFile; fileRef = 30A3D6531667F11C00C49A39 /* GTDiff.m */; };
+ 30B1E7EE1703522100D0814D /* NSDate+GTTimeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B1E7EC1703522100D0814D /* NSDate+GTTimeAdditions.h */; };
+ 30B1E7EF1703522100D0814D /* NSDate+GTTimeAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 30B1E7EC1703522100D0814D /* NSDate+GTTimeAdditions.h */; };
+ 30B1E7F01703522100D0814D /* NSDate+GTTimeAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B1E7ED1703522100D0814D /* NSDate+GTTimeAdditions.m */; };
+ 30B1E7F11703522100D0814D /* NSDate+GTTimeAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B1E7ED1703522100D0814D /* NSDate+GTTimeAdditions.m */; };
+ 30B1E8001703871900D0814D /* GTTimeAdditionsSpec.m in Sources */ = {isa = PBXBuildFile; fileRef = 30B1E7FF1703871900D0814D /* GTTimeAdditionsSpec.m */; };
30FDC07F16835A8100654BF0 /* GTDiffLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 30FDC07D16835A8100654BF0 /* GTDiffLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
30FDC08016835A8100654BF0 /* GTDiffLine.h in Headers */ = {isa = PBXBuildFile; fileRef = 30FDC07D16835A8100654BF0 /* GTDiffLine.h */; settings = {ATTRIBUTES = (Public, ); }; };
30FDC08116835A8100654BF0 /* GTDiffLine.m in Sources */ = {isa = PBXBuildFile; fileRef = 30FDC07E16835A8100654BF0 /* GTDiffLine.m */; };
@@ -297,6 +302,9 @@
30865A90167F503400B1AB6E /* GTDiffSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiffSpec.m; sourceTree = "<group>"; };
30A3D6521667F11C00C49A39 /* GTDiff.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTDiff.h; sourceTree = "<group>"; };
30A3D6531667F11C00C49A39 /* GTDiff.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiff.m; sourceTree = "<group>"; };
+ 30B1E7EC1703522100D0814D /* NSDate+GTTimeAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSDate+GTTimeAdditions.h"; sourceTree = "<group>"; };
+ 30B1E7ED1703522100D0814D /* NSDate+GTTimeAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+GTTimeAdditions.m"; sourceTree = "<group>"; };
+ 30B1E7FF1703871900D0814D /* GTTimeAdditionsSpec.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTTimeAdditionsSpec.m; sourceTree = "<group>"; };
30FDC07D16835A8100654BF0 /* GTDiffLine.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GTDiffLine.h; sourceTree = "<group>"; };
30FDC07E16835A8100654BF0 /* GTDiffLine.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GTDiffLine.m; sourceTree = "<group>"; };
32DBCF5E0370ADEE00C91783 /* ObjectiveGitFramework_Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectiveGitFramework_Prefix.pch; sourceTree = "<group>"; };
@@ -536,6 +544,7 @@
88F05AAE16011FFD00B7AD1D /* GTWalkerTest.m */,
30865A90167F503400B1AB6E /* GTDiffSpec.m */,
88A994B916FCE7D400402C7B /* GTBranchSpec.m */,
+ 30B1E7FF1703871900D0814D /* GTTimeAdditionsSpec.m */,
88C0BC5817038CF3009E99AA /* GTConfigurationSpec.m */,
88F05AAF16011FFD00B7AD1D /* ObjectiveGitTests-Info.plist */,
88F05AB016011FFD00B7AD1D /* ObjectiveGitTests-Prefix.pch */,
@@ -661,6 +670,8 @@
BDE4C061130EFE2C00851650 /* NSError+Git.m */,
55C8057213874CDF004DCB0F /* NSString+Git.h */,
55C8057313874CDF004DCB0F /* NSString+Git.m */,
+ 30B1E7EC1703522100D0814D /* NSDate+GTTimeAdditions.h */,
+ 30B1E7ED1703522100D0814D /* NSDate+GTTimeAdditions.m */,
);
path = Categories;
sourceTree = "<group>";
@@ -700,6 +711,7 @@
3011D8781668F29600CE3409 /* GTDiffDelta.h in Headers */,
6A74CA3516A942B400E1A3C5 /* GTRepository+Private.h in Headers */,
6A74CA3616A942C000E1A3C5 /* GTConfiguration+Private.h in Headers */,
+ 30B1E7EF1703522100D0814D /* NSDate+GTTimeAdditions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -735,6 +747,7 @@
30FDC07F16835A8100654BF0 /* GTDiffLine.h in Headers */,
3011D8771668F29600CE3409 /* GTDiffDelta.h in Headers */,
8849C6A214AD81FF003890AF /* GTRepository+Private.h in Headers */,
+ 30B1E7EE1703522100D0814D /* NSDate+GTTimeAdditions.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -983,6 +996,7 @@
3011D8741668E78500CE3409 /* GTDiffHunk.m in Sources */,
3011D87A1668F29600CE3409 /* GTDiffDelta.m in Sources */,
30FDC08216835A8100654BF0 /* GTDiffLine.m in Sources */,
+ 30B1E7F11703522100D0814D /* NSDate+GTTimeAdditions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1008,6 +1022,7 @@
30865A91167F503400B1AB6E /* GTDiffSpec.m in Sources */,
88A994BA16FCE7D400402C7B /* GTBranchSpec.m in Sources */,
88A994CB16FCED1D00402C7B /* GTTestCase.m in Sources */,
+ 30B1E8001703871900D0814D /* GTTimeAdditionsSpec.m in Sources */,
88C0BC5917038CF3009E99AA /* GTConfigurationSpec.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
@@ -1041,6 +1056,7 @@
3011D8731668E78500CE3409 /* GTDiffHunk.m in Sources */,
3011D8791668F29600CE3409 /* GTDiffDelta.m in Sources */,
30FDC08116835A8100654BF0 /* GTDiffLine.m in Sources */,
+ 30B1E7F01703522100D0814D /* NSDate+GTTimeAdditions.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
53 ObjectiveGitTests/GTTimeAdditionsSpec.m
@@ -0,0 +1,53 @@
+//
+// GTTimeAdditionsSpec.m
+// ObjectiveGitFramework
+//
+// Created by Danny Greg on 27/03/2013.
+// Copyright (c) 2013 GitHub, Inc. All rights reserved.
+//
+
+#import "NSDate+GTTimeAdditions.h"
+
+SpecBegin(GTTimeAdditions)
+
+describe(@"Conversion between git_time and NSDate", ^{
+ it(@"should be able to create a correct NSDate and NSTimeZone when given a git_time", ^{
+ git_time_t seconds = 1265374800;
+ int offset = -120; //2 hours behind GMT
+ git_time time = (git_time){ .time = seconds, .offset = offset };
+ NSDate *date = [NSDate gt_dateFromGitTime:time];
+ expect(date).toNot.beNil();
+
+ NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
+ NSDateComponents *components = [gregorianCalendar components:NSDayCalendarUnit | NSMonthCalendarUnit | NSYearCalendarUnit | NSHourCalendarUnit fromDate:date];
+ expect(components).toNot.beNil();
+
+ expect(components.day).to.equal(5);
+ expect(components.month).to.equal(2);
+ expect(components.year).to.equal(2010);
+ expect(components.hour).to.equal(13);
+
+ NSTimeZone *timeZone = [NSTimeZone gt_timeZoneFromGitTime:time];
+ expect(timeZone).toNot.beNil();
+ NSInteger expectedSecondsFromGMT = -120 * 60;
+ expect(timeZone.secondsFromGMT).to.equal(expectedSecondsFromGMT);
+ });
+
+ it(@"should return a correct offset for an NSTimeZone", ^{
+ NSTimeZone *timeZone = [NSTimeZone timeZoneForSecondsFromGMT:180 * 60];
+ expect(timeZone).toNot.beNil();
+ expect(timeZone.gt_gitTimeOffset).to.equal(180);
+ });
+
+ it(@"should return a correct git_time for an NSDate", ^{
+ NSDate *date = [NSDate dateWithString:@"2010-05-12 18:29:13 +0000"];
+ expect(date).toNot.beNil();
+
+ NSTimeZone *twoHoursAheadOfGMT = [NSTimeZone timeZoneForSecondsFromGMT:120 * 60];
+ git_time time = [date gt_gitTimeUsingTimeZone:twoHoursAheadOfGMT];
+ expect(time.time).to.equal(1273688953);
+ expect(time.offset).to.equal(120);
+ });
+});
+
+SpecEnd
Please sign in to comment.
Something went wrong with that request. Please try again.