我应该使用 NSDate 来跟踪到达时间和迟到时间吗?
Should I use NSDate to track arrival time and lateness?
我想做时间计算,不知道用什么class,我应该用NSDate
吗?
我希望用户输入他每天应该上班的时间,然后该应用会显示他的平均 late/early 时间(以分钟为单位)。
更好的解释:
当用户第一次启动应用程序时,应用程序会询问他应该在什么时候上班以及什么时候应该离开。该应用程序跟踪用户 arrives/leaves 的时间(使用工作地址和地理围栏)并计算用户上班的平均迟到和平均早到。当用户打开应用程序时,他会看到两个标签,一个用于 "average late",一个用于 "average early"。
我应该使用 NSDate
还是有更好的方法?
如果您只是比较持续时间,NSTimeInterval
是适合您的类型(它实际上是 float
毫秒数,可以解释其对 reader 的意图)。
NSDate
对于需要以实际时钟时间开始或结束的计算是必需的。
编辑 描述更具体的问题:给定用户每天的工作开始时间,计算与到达工作时间的偏差,关键计算涉及NSDate
.
它旨在回答以下问题:与实际时钟相比,用户现在是否准时?此计算的关键参数是当前时间 NSDate
和用户计划到达时间 NSDate
,可以将其保存为简单标量并通过 NSDateComponents
...[=18= 转换为 NSDate ]
// core location triggered an arrival notification and we call this
// assumes a "User" class that knows user state, like the time user is due at work
-(void)userJustArrived:(User *)myUser {
NSDate *now = [NSDate date];
NSDate *dueAtWork = [myUser dueAtWork];
NSTimeInterval lateness = [now timeIntervalSinceDate:dueAtWork];
// a negative lateness means user is early
if (lateness > 0)
NSLog(@"you are %f milliseconds late. perhaps you should go into standup comedy", lateness);
}
// on the user class, due at work produces an NSDate from what you would
// have stored earlier as the time when a user is expected at work
- (NSDate *)dueAtWork {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
// these are given as user state, the user's planned start time
components.hour = self.dueAtWorkHour;
components.minute = self.dueAtWorkMinute;
return [components date];
}
通常,如果您想跟踪 "human" 时间(即您可以在日历或时钟上找到的日期和时间),您需要的工具是 NSDateComponents
,再加上 NSCalendar
。 NSDate
的目标是及时跟踪绝对时刻,(*) 自某个参考时刻以来的秒数,这通常不是人们对时间的看法。 NSDate
一旦处理时区、夏令时或任何其他扰乱 "seconds since the epoch" 和 "the clock on the wall."[=17 的良好映射的事情,NSDate
很快就会变得不正确并且常常适得其反=]
(*) 抛开相对论等等,假设我们都能就事情发生的时间达成一致,并且时间间隔可以在一个美好、简单的牛顿宇宙中以交换和传递的方式组合。还要忽略诸如闰秒或任何其他可能使事情变得复杂的问题,并且您有 NSDate
.
这是一个实际的实现,应该可以处理大多数怪事(比如午夜时间)。可能无法正确处理 DST 转换,但它应该能让您走上正确的轨道。
let twelveHours: NSTimeInterval = 12 * 60 * 60
func timeLateBetweenDate(actualDate: NSDate, nominalHour: Int, nominalMinute: Int) -> NSTimeInterval {
func timeLateOnDate(onDate: NSDate) -> NSTimeInterval {
let calendar = NSCalendar.currentCalendar()
let expectedDate = calendar.dateBySettingHour(nominalHour, minute: nominalMinute, second: 0, ofDate: onDate, options: [])!
let todayDifference = actualDate.timeIntervalSinceDate(expectedDate)
if todayDifference > twelveHours { // Over 12 hours late; should have checked against tomorrow
return timeLateOnDate(calendar.dateByAddingUnit(.Day, value: 1, toDate: onDate, options: [])!)
} else if todayDifference < -twelveHours { // Over 12 hours early, should have checked against yesterday
return timeLateOnDate(calendar.dateByAddingUnit(.Day, value: -1, toDate: onDate, options: [])!)
}
else {
return todayDifference
}
}
return timeLateOnDate(actualDate)
}
在有点草率的 ObjC 中(只是音译 Swift;作为一种方法,这可能会更清楚):
NSTimeInterval twelveHours = 12 * 60 * 60;
NSTimeInterval _timeLateOnDate(NSDate *onDate, NSDate *actualDate, NSUInteger nominalHour, NSUInteger nominalMinute) {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *expectedDate = [calendar dateBySettingHour:nominalHour minute: nominalMinute second: 0 ofDate: onDate options: 0];
NSTimeInterval todayDifference = [actualDate timeIntervalSinceDate:expectedDate];
if (todayDifference > twelveHours) { // Over 12 hours late; should have checked against tomorrow
return _timeLateOnDate([calendar dateByAddingUnit:NSCalendarUnitDay value: 1 toDate: onDate options: 0],
actualDate, nominalHour, nominalMinute);
} else if (todayDifference < -twelveHours) { // Over 12 hours early, should have checked against yesterday
return _timeLateOnDate([calendar dateByAddingUnit:NSCalendarUnitDay value: -1 toDate: onDate options: 0],
actualDate, nominalHour, nominalMinute);
} else {
return todayDifference;
}
}
NSTimeInterval timeLateBetweenDateAndNominalHourMinute(NSDate *actualDate, NSUInteger nominalHour, NSUInteger nominalMinute) {
return _timeLateOnDate(actualDate, actualDate, nominalHour, nominalMinute);
}
您可以使用NSDateFormatter
来设置每天的实际办公时间。在 NSTimeInterval
上使用 timeIntervalSinceDate:
方法以秒为单位计算迟到/早的平均值。
您要存储的时间不是日期。 "Februrary 9th 2016 10:20:30.7 UTC" 之类的东西是一个日期。 “早上 8 点 30 分”不是 NSDate 可以表示的日期。
当用户输入时间时,将小时和分钟存储为两个数字。
当用户上班时,获取当前日期,将其转换为具有本地日历的日期组件以获得今天的日期,创建一个包含今天日期和用户输入的小时和分钟的 NSDate,然后你可以比较两个 NSDates。这样,您就可以自动处理夏令时等。您甚至可以处理用户在距您 6 小时的时区度假时输入日期的情况。
请不要索要密码。编写代码是你的工作。你一个人的工作。
我想做时间计算,不知道用什么class,我应该用NSDate
吗?
我希望用户输入他每天应该上班的时间,然后该应用会显示他的平均 late/early 时间(以分钟为单位)。
更好的解释: 当用户第一次启动应用程序时,应用程序会询问他应该在什么时候上班以及什么时候应该离开。该应用程序跟踪用户 arrives/leaves 的时间(使用工作地址和地理围栏)并计算用户上班的平均迟到和平均早到。当用户打开应用程序时,他会看到两个标签,一个用于 "average late",一个用于 "average early"。
我应该使用 NSDate
还是有更好的方法?
如果您只是比较持续时间,NSTimeInterval
是适合您的类型(它实际上是 float
毫秒数,可以解释其对 reader 的意图)。
NSDate
对于需要以实际时钟时间开始或结束的计算是必需的。
编辑 描述更具体的问题:给定用户每天的工作开始时间,计算与到达工作时间的偏差,关键计算涉及NSDate
.
它旨在回答以下问题:与实际时钟相比,用户现在是否准时?此计算的关键参数是当前时间 NSDate
和用户计划到达时间 NSDate
,可以将其保存为简单标量并通过 NSDateComponents
...[=18= 转换为 NSDate ]
// core location triggered an arrival notification and we call this
// assumes a "User" class that knows user state, like the time user is due at work
-(void)userJustArrived:(User *)myUser {
NSDate *now = [NSDate date];
NSDate *dueAtWork = [myUser dueAtWork];
NSTimeInterval lateness = [now timeIntervalSinceDate:dueAtWork];
// a negative lateness means user is early
if (lateness > 0)
NSLog(@"you are %f milliseconds late. perhaps you should go into standup comedy", lateness);
}
// on the user class, due at work produces an NSDate from what you would
// have stored earlier as the time when a user is expected at work
- (NSDate *)dueAtWork {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDateComponents *components = [calendar components:(NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay) fromDate:[NSDate date]];
// these are given as user state, the user's planned start time
components.hour = self.dueAtWorkHour;
components.minute = self.dueAtWorkMinute;
return [components date];
}
通常,如果您想跟踪 "human" 时间(即您可以在日历或时钟上找到的日期和时间),您需要的工具是 NSDateComponents
,再加上 NSCalendar
。 NSDate
的目标是及时跟踪绝对时刻,(*) 自某个参考时刻以来的秒数,这通常不是人们对时间的看法。 NSDate
一旦处理时区、夏令时或任何其他扰乱 "seconds since the epoch" 和 "the clock on the wall."[=17 的良好映射的事情,NSDate
很快就会变得不正确并且常常适得其反=]
(*) 抛开相对论等等,假设我们都能就事情发生的时间达成一致,并且时间间隔可以在一个美好、简单的牛顿宇宙中以交换和传递的方式组合。还要忽略诸如闰秒或任何其他可能使事情变得复杂的问题,并且您有 NSDate
.
这是一个实际的实现,应该可以处理大多数怪事(比如午夜时间)。可能无法正确处理 DST 转换,但它应该能让您走上正确的轨道。
let twelveHours: NSTimeInterval = 12 * 60 * 60
func timeLateBetweenDate(actualDate: NSDate, nominalHour: Int, nominalMinute: Int) -> NSTimeInterval {
func timeLateOnDate(onDate: NSDate) -> NSTimeInterval {
let calendar = NSCalendar.currentCalendar()
let expectedDate = calendar.dateBySettingHour(nominalHour, minute: nominalMinute, second: 0, ofDate: onDate, options: [])!
let todayDifference = actualDate.timeIntervalSinceDate(expectedDate)
if todayDifference > twelveHours { // Over 12 hours late; should have checked against tomorrow
return timeLateOnDate(calendar.dateByAddingUnit(.Day, value: 1, toDate: onDate, options: [])!)
} else if todayDifference < -twelveHours { // Over 12 hours early, should have checked against yesterday
return timeLateOnDate(calendar.dateByAddingUnit(.Day, value: -1, toDate: onDate, options: [])!)
}
else {
return todayDifference
}
}
return timeLateOnDate(actualDate)
}
在有点草率的 ObjC 中(只是音译 Swift;作为一种方法,这可能会更清楚):
NSTimeInterval twelveHours = 12 * 60 * 60;
NSTimeInterval _timeLateOnDate(NSDate *onDate, NSDate *actualDate, NSUInteger nominalHour, NSUInteger nominalMinute) {
NSCalendar *calendar = [NSCalendar currentCalendar];
NSDate *expectedDate = [calendar dateBySettingHour:nominalHour minute: nominalMinute second: 0 ofDate: onDate options: 0];
NSTimeInterval todayDifference = [actualDate timeIntervalSinceDate:expectedDate];
if (todayDifference > twelveHours) { // Over 12 hours late; should have checked against tomorrow
return _timeLateOnDate([calendar dateByAddingUnit:NSCalendarUnitDay value: 1 toDate: onDate options: 0],
actualDate, nominalHour, nominalMinute);
} else if (todayDifference < -twelveHours) { // Over 12 hours early, should have checked against yesterday
return _timeLateOnDate([calendar dateByAddingUnit:NSCalendarUnitDay value: -1 toDate: onDate options: 0],
actualDate, nominalHour, nominalMinute);
} else {
return todayDifference;
}
}
NSTimeInterval timeLateBetweenDateAndNominalHourMinute(NSDate *actualDate, NSUInteger nominalHour, NSUInteger nominalMinute) {
return _timeLateOnDate(actualDate, actualDate, nominalHour, nominalMinute);
}
您可以使用NSDateFormatter
来设置每天的实际办公时间。在 NSTimeInterval
上使用 timeIntervalSinceDate:
方法以秒为单位计算迟到/早的平均值。
您要存储的时间不是日期。 "Februrary 9th 2016 10:20:30.7 UTC" 之类的东西是一个日期。 “早上 8 点 30 分”不是 NSDate 可以表示的日期。
当用户输入时间时,将小时和分钟存储为两个数字。
当用户上班时,获取当前日期,将其转换为具有本地日历的日期组件以获得今天的日期,创建一个包含今天日期和用户输入的小时和分钟的 NSDate,然后你可以比较两个 NSDates。这样,您就可以自动处理夏令时等。您甚至可以处理用户在距您 6 小时的时区度假时输入日期的情况。
请不要索要密码。编写代码是你的工作。你一个人的工作。