NSCalendar.components().minute 返回不一致的值
NSCalendar.components().minute returning inconsistent values
原来的问题是我在下面link测试和编码的post中遇到的
这是最小的测试用例
- 我正在创建一个偏离特定日期的日期(此日期中的自我
我在 NSDate() 扩展中做的情况)使用
NSCalendar.dateByAddingUnit(..., value:x, ...)
- 然后我使用 NSCalendar.components(..., fromDate, toDate,
....).分钟
- 如果x>0,我在上面的步骤中得到的答案是x-1。如果 x<0,则
我得到的答案是 x。 x 在上面的步骤 1 中定义。
- 这可能会导致使用人类可读属性过滤事件的应用程序出现错误,例如过去 3 小时内的所有事件,因为由于此行为,180 分钟不是三小时。
- 这不是步骤 1 中的错误,因为日期打印正确,如所见
在 post.
末尾的打印输出中
NSCalendar.components 中是否有我遗漏的选项或者这是一个错误?
这是代码。
//
// NSDateTest.swift
// NSDateTestCase
//
// Created by Jitendra Kulkarni on 6/13/15.
//
import Foundation
public extension NSDate {
func xMins(x:Int) -> NSDate {
return NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitMinute, value: x, toDate: self, options: nil)!
}
var hoursFromToday: Int{
var fromDate: NSDate = self
var toDate: NSDate = NSDate()
var sign: Int = -1
(fromDate,toDate, sign) = self.sanitizedDates()
return (sign * NSCalendar.currentCalendar().components(.CalendarUnitHour, fromDate: fromDate, toDate: toDate, options: nil).hour)
}
var minsFromToday: Int{
var fromDate: NSDate = self
var toDate: NSDate = NSDate()
var sign: Int = 1
(fromDate,toDate) = self.sanitizedDates()
return ( sign * NSCalendar.currentCalendar().components(.CalendarUnitMinute, fromDate: fromDate, toDate: toDate, options: nil).minute)
}
//Date Comparisons
//
func isGreaterThanDate(dateToCompare : NSDate) -> Bool
{
//Declare Variables
var isGreater = false
//Compare Values
if self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
{
isGreater = true
}
//Return Result
return isGreater
}
// Date printing conversions
var timeDayMonthYear: String {
let dateMonthYearFormatter: NSDateFormatter = NSDateFormatter()
let currentLocale: NSLocale = NSLocale.currentLocale()
let dateMonthYearFormatString: NSString! = NSDateFormatter.dateFormatFromTemplate("EdMMMyyyy' ' HH':'mm",options: 0, locale: currentLocale)
dateMonthYearFormatter.dateFormat = dateMonthYearFormatString as! String
return dateMonthYearFormatter.stringFromDate(self)
}
private func sanitizedDates() -> (fromDate: NSDate, toDate: NSDate) {
var toDate: NSDate = self
var fromDate: NSDate = NSDate()
if(toDate.isGreaterThanDate(fromDate)) {
// toDate = toDate.xMins(1) // Uncomment this to make the answer work
}
return (fromDate,toDate)
}
static func test (mins: Int = 0) {
NSLog("****************** Start Testing of NSDate **************************")
NSLog("Inputs: mins: \(mins)")
var today = NSDate()
NSLog("Today is: \(today.timeDayMonthYear)")
var minsFromToday = today.xMins(mins)
NSLog("** Date created \(mins) minutes from today is: \(minsFromToday.timeDayMonthYear)")
NSLog("minsFromToday returns: \(minsFromToday.minsFromToday)");
NSLog("hoursFromToday returns: \(minsFromToday.hoursFromToday)");
NSLog("__________________ End Testing of NSDate _________________________")
}
}
这是 NSDate(60) 后跟 NSDate(-60) 的结果。查找 *ERROR。如果您从 sanitizedDate() 中的一个注释行中删除注释,您将得到预期的结果。
2015-06-13 14:56:44.877 NSDateTestCase[23136:1150501] ****************** Start Testing of NSDate **************************
2015-06-13 14:56:44.878 NSDateTestCase[23136:1150501] Inputs: mins: 60
2015-06-13 14:56:44.882 NSDateTestCase[23136:1150501] Today is: Sat, Jun 13, 2015, 14:56
2015-06-13 14:56:44.883 NSDateTestCase[23136:1150501] ** Date created 60 minutes from today is: Sat, Jun 13, 2015, 15:56
2015-06-13 14:56:44.883 NSDateTestCase[23136:1150501] minsFromToday returns: 59 // *ERROR should be 60
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] hoursFromToday returns: 0 // *ERROR should be 1
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] __________________ End Testing of NSDate _________________________
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] ****************** Start Testing of NSDate **************************
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] Inputs: mins: -60
2015-06-13 14:56:44.885 NSDateTestCase[23136:1150501] Today is: Sat, Jun 13, 2015, 14:56
2015-06-13 14:56:44.885 NSDateTestCase[23136:1150501] ** Date created -60 minutes from today is: Sat, Jun 13, 2015, 13:56
2015-06-13 14:56:44.886 NSDateTestCase[23136:1150501] minsFromToday returns: -60
2015-06-13 14:56:44.886 NSDateTestCase[23136:1150501] hoursFromToday returns: -1
2015-06-13 14:56:44.893 NSDateTestCase[23136:1150501] __________________ End Testing of NSDate _________________________
下面是基于 Kurt 的回答的代码。请注意,必须更改 xFromToday API 以获取有关 "today":
的输入
//
// NSDateTest.swift
// NSDateTestCase
//
// Created by Jitendra Kulkarni on 6/13/15.
//
import Foundation
public extension NSDate {
func xMins(x:Int) -> NSDate {
return NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitMinute, value: x, toDate: self, options: nil)!
}
func hoursFromToday(today: NSDate) -> Int {
var fromDate: NSDate = self
var toDate: NSDate = today
return (-NSCalendar.currentCalendar().components(.CalendarUnitHour, fromDate: fromDate, toDate: toDate, options: nil).hour)
}
func minsFromToday(today: NSDate) -> Int {
var fromDate: NSDate = self
var toDate: NSDate = today
return (-NSCalendar.currentCalendar().components(.CalendarUnitMinute, fromDate: fromDate, toDate: toDate, options: nil).minute)
}
//Date Comparisions
//
func isGreaterThanDate(dateToCompare : NSDate) -> Bool
{
//Declare Variables
var isGreater = false
//Compare Values
if self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
{
isGreater = true
}
//Return Result
return isGreater
}
// Date printing converstions
var timeDayMonthYear: String {
let dateMonthYearFormatter: NSDateFormatter = NSDateFormatter()
let currentLocale: NSLocale = NSLocale.currentLocale()
let dateMonthYearFormatString: NSString! = NSDateFormatter.dateFormatFromTemplate("EdMMMyyyy' ' HH':'mm",options: 0, locale: currentLocale)
dateMonthYearFormatter.dateFormat = dateMonthYearFormatString as! String
return dateMonthYearFormatter.stringFromDate(self)
}
static func test (mins: Int = 0) {
NSLog("****************** Start Testing of NSDate **************************")
NSLog("Inputs: mins: \(mins)")
var today = NSDate()
NSLog("Today is: \(today.timeDayMonthYear)")
var minsFromToday = today.xMins(mins)
NSLog("** Date created \(mins) minutes from today is: \(minsFromToday.timeDayMonthYear)")
//NSLog("minsFromToday returns: \(minsFromToday.minsFromToday)")
NSLog("minsFromToday(today) returns: \(minsFromToday.minsFromToday(today))");
//NSLog("hoursFromToday returns: \(minsFromToday.hoursFromToday)")
NSLog("hoursFromToday(today) returns: \(minsFromToday.hoursFromToday(today))");
NSLog("__________________ End Testing of NSDate _________________________")
}
这是生成的输出:
2015-06-13 16:23:55.362 NSDateTestCase[23758:1196619] ****************** Start Testing of NSDate **************************
2015-06-13 16:23:55.363 NSDateTestCase[23758:1196619] Inputs: mins: 60
2015-06-13 16:23:55.366 NSDateTestCase[23758:1196619] Today is: Sat, Jun 13, 2015, 16:23
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] ** Date created 60 minutes from today is: Sat, Jun 13, 2015, 17:23
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] minsFromToday(today) returns: 60 // All good now.
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] hoursFromToday(today) returns: 1 // All good now.
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] __________________ End Testing of NSDate _________________________
2015-06-13 16:23:55.368 NSDateTestCase[23758:1196619] ****************** Start Testing of NSDate **************************
2015-06-13 16:23:55.368 NSDateTestCase[23758:1196619] Inputs: mins: -60
2015-06-13 16:23:55.368 NSDateTestCase[23758:1196619] Today is: Sat, Jun 13, 2015, 16:23
2015-06-13 16:23:55.369 NSDateTestCase[23758:1196619] ** Date created -60 minutes from today is: Sat, Jun 13, 2015, 15:23
2015-06-13 16:23:55.370 NSDateTestCase[23758:1196619] minsFromToday(today) returns: -60
2015-06-13 16:23:55.380 NSDateTestCase[23758:1196619] hoursFromToday(today) returns: -1
2015-06-13 16:23:55.381 NSDateTestCase[23758:1196619] __________________ End Testing of NSDate _________________________
您在代码中的 4 个不同位置调用 NSDate()
。
每个人都会 return 当前日期和时间 当该代码执行时, 因此它们会相差几分之一秒。
我怀疑您想在整个计算中对 "today" 使用一个一致的值。在代码的开头调用 NSDate()
一次,将其存储在一个变量中,并一致地引用该变量。
原来的问题是我在下面link测试和编码的post中遇到的
这是最小的测试用例
- 我正在创建一个偏离特定日期的日期(此日期中的自我 我在 NSDate() 扩展中做的情况)使用 NSCalendar.dateByAddingUnit(..., value:x, ...)
- 然后我使用 NSCalendar.components(..., fromDate, toDate, ....).分钟
- 如果x>0,我在上面的步骤中得到的答案是x-1。如果 x<0,则 我得到的答案是 x。 x 在上面的步骤 1 中定义。
- 这可能会导致使用人类可读属性过滤事件的应用程序出现错误,例如过去 3 小时内的所有事件,因为由于此行为,180 分钟不是三小时。
- 这不是步骤 1 中的错误,因为日期打印正确,如所见 在 post. 末尾的打印输出中
NSCalendar.components 中是否有我遗漏的选项或者这是一个错误?
这是代码。
//
// NSDateTest.swift
// NSDateTestCase
//
// Created by Jitendra Kulkarni on 6/13/15.
//
import Foundation
public extension NSDate {
func xMins(x:Int) -> NSDate {
return NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitMinute, value: x, toDate: self, options: nil)!
}
var hoursFromToday: Int{
var fromDate: NSDate = self
var toDate: NSDate = NSDate()
var sign: Int = -1
(fromDate,toDate, sign) = self.sanitizedDates()
return (sign * NSCalendar.currentCalendar().components(.CalendarUnitHour, fromDate: fromDate, toDate: toDate, options: nil).hour)
}
var minsFromToday: Int{
var fromDate: NSDate = self
var toDate: NSDate = NSDate()
var sign: Int = 1
(fromDate,toDate) = self.sanitizedDates()
return ( sign * NSCalendar.currentCalendar().components(.CalendarUnitMinute, fromDate: fromDate, toDate: toDate, options: nil).minute)
}
//Date Comparisons
//
func isGreaterThanDate(dateToCompare : NSDate) -> Bool
{
//Declare Variables
var isGreater = false
//Compare Values
if self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
{
isGreater = true
}
//Return Result
return isGreater
}
// Date printing conversions
var timeDayMonthYear: String {
let dateMonthYearFormatter: NSDateFormatter = NSDateFormatter()
let currentLocale: NSLocale = NSLocale.currentLocale()
let dateMonthYearFormatString: NSString! = NSDateFormatter.dateFormatFromTemplate("EdMMMyyyy' ' HH':'mm",options: 0, locale: currentLocale)
dateMonthYearFormatter.dateFormat = dateMonthYearFormatString as! String
return dateMonthYearFormatter.stringFromDate(self)
}
private func sanitizedDates() -> (fromDate: NSDate, toDate: NSDate) {
var toDate: NSDate = self
var fromDate: NSDate = NSDate()
if(toDate.isGreaterThanDate(fromDate)) {
// toDate = toDate.xMins(1) // Uncomment this to make the answer work
}
return (fromDate,toDate)
}
static func test (mins: Int = 0) {
NSLog("****************** Start Testing of NSDate **************************")
NSLog("Inputs: mins: \(mins)")
var today = NSDate()
NSLog("Today is: \(today.timeDayMonthYear)")
var minsFromToday = today.xMins(mins)
NSLog("** Date created \(mins) minutes from today is: \(minsFromToday.timeDayMonthYear)")
NSLog("minsFromToday returns: \(minsFromToday.minsFromToday)");
NSLog("hoursFromToday returns: \(minsFromToday.hoursFromToday)");
NSLog("__________________ End Testing of NSDate _________________________")
}
}
这是 NSDate(60) 后跟 NSDate(-60) 的结果。查找 *ERROR。如果您从 sanitizedDate() 中的一个注释行中删除注释,您将得到预期的结果。
2015-06-13 14:56:44.877 NSDateTestCase[23136:1150501] ****************** Start Testing of NSDate **************************
2015-06-13 14:56:44.878 NSDateTestCase[23136:1150501] Inputs: mins: 60
2015-06-13 14:56:44.882 NSDateTestCase[23136:1150501] Today is: Sat, Jun 13, 2015, 14:56
2015-06-13 14:56:44.883 NSDateTestCase[23136:1150501] ** Date created 60 minutes from today is: Sat, Jun 13, 2015, 15:56
2015-06-13 14:56:44.883 NSDateTestCase[23136:1150501] minsFromToday returns: 59 // *ERROR should be 60
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] hoursFromToday returns: 0 // *ERROR should be 1
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] __________________ End Testing of NSDate _________________________
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] ****************** Start Testing of NSDate **************************
2015-06-13 14:56:44.884 NSDateTestCase[23136:1150501] Inputs: mins: -60
2015-06-13 14:56:44.885 NSDateTestCase[23136:1150501] Today is: Sat, Jun 13, 2015, 14:56
2015-06-13 14:56:44.885 NSDateTestCase[23136:1150501] ** Date created -60 minutes from today is: Sat, Jun 13, 2015, 13:56
2015-06-13 14:56:44.886 NSDateTestCase[23136:1150501] minsFromToday returns: -60
2015-06-13 14:56:44.886 NSDateTestCase[23136:1150501] hoursFromToday returns: -1
2015-06-13 14:56:44.893 NSDateTestCase[23136:1150501] __________________ End Testing of NSDate _________________________
下面是基于 Kurt 的回答的代码。请注意,必须更改 xFromToday API 以获取有关 "today":
的输入//
// NSDateTest.swift
// NSDateTestCase
//
// Created by Jitendra Kulkarni on 6/13/15.
//
import Foundation
public extension NSDate {
func xMins(x:Int) -> NSDate {
return NSCalendar.currentCalendar().dateByAddingUnit(.CalendarUnitMinute, value: x, toDate: self, options: nil)!
}
func hoursFromToday(today: NSDate) -> Int {
var fromDate: NSDate = self
var toDate: NSDate = today
return (-NSCalendar.currentCalendar().components(.CalendarUnitHour, fromDate: fromDate, toDate: toDate, options: nil).hour)
}
func minsFromToday(today: NSDate) -> Int {
var fromDate: NSDate = self
var toDate: NSDate = today
return (-NSCalendar.currentCalendar().components(.CalendarUnitMinute, fromDate: fromDate, toDate: toDate, options: nil).minute)
}
//Date Comparisions
//
func isGreaterThanDate(dateToCompare : NSDate) -> Bool
{
//Declare Variables
var isGreater = false
//Compare Values
if self.compare(dateToCompare) == NSComparisonResult.OrderedDescending
{
isGreater = true
}
//Return Result
return isGreater
}
// Date printing converstions
var timeDayMonthYear: String {
let dateMonthYearFormatter: NSDateFormatter = NSDateFormatter()
let currentLocale: NSLocale = NSLocale.currentLocale()
let dateMonthYearFormatString: NSString! = NSDateFormatter.dateFormatFromTemplate("EdMMMyyyy' ' HH':'mm",options: 0, locale: currentLocale)
dateMonthYearFormatter.dateFormat = dateMonthYearFormatString as! String
return dateMonthYearFormatter.stringFromDate(self)
}
static func test (mins: Int = 0) {
NSLog("****************** Start Testing of NSDate **************************")
NSLog("Inputs: mins: \(mins)")
var today = NSDate()
NSLog("Today is: \(today.timeDayMonthYear)")
var minsFromToday = today.xMins(mins)
NSLog("** Date created \(mins) minutes from today is: \(minsFromToday.timeDayMonthYear)")
//NSLog("minsFromToday returns: \(minsFromToday.minsFromToday)")
NSLog("minsFromToday(today) returns: \(minsFromToday.minsFromToday(today))");
//NSLog("hoursFromToday returns: \(minsFromToday.hoursFromToday)")
NSLog("hoursFromToday(today) returns: \(minsFromToday.hoursFromToday(today))");
NSLog("__________________ End Testing of NSDate _________________________")
}
这是生成的输出:
2015-06-13 16:23:55.362 NSDateTestCase[23758:1196619] ****************** Start Testing of NSDate **************************
2015-06-13 16:23:55.363 NSDateTestCase[23758:1196619] Inputs: mins: 60
2015-06-13 16:23:55.366 NSDateTestCase[23758:1196619] Today is: Sat, Jun 13, 2015, 16:23
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] ** Date created 60 minutes from today is: Sat, Jun 13, 2015, 17:23
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] minsFromToday(today) returns: 60 // All good now.
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] hoursFromToday(today) returns: 1 // All good now.
2015-06-13 16:23:55.367 NSDateTestCase[23758:1196619] __________________ End Testing of NSDate _________________________
2015-06-13 16:23:55.368 NSDateTestCase[23758:1196619] ****************** Start Testing of NSDate **************************
2015-06-13 16:23:55.368 NSDateTestCase[23758:1196619] Inputs: mins: -60
2015-06-13 16:23:55.368 NSDateTestCase[23758:1196619] Today is: Sat, Jun 13, 2015, 16:23
2015-06-13 16:23:55.369 NSDateTestCase[23758:1196619] ** Date created -60 minutes from today is: Sat, Jun 13, 2015, 15:23
2015-06-13 16:23:55.370 NSDateTestCase[23758:1196619] minsFromToday(today) returns: -60
2015-06-13 16:23:55.380 NSDateTestCase[23758:1196619] hoursFromToday(today) returns: -1
2015-06-13 16:23:55.381 NSDateTestCase[23758:1196619] __________________ End Testing of NSDate _________________________
您在代码中的 4 个不同位置调用 NSDate()
。
每个人都会 return 当前日期和时间 当该代码执行时, 因此它们会相差几分之一秒。
我怀疑您想在整个计算中对 "today" 使用一个一致的值。在代码的开头调用 NSDate()
一次,将其存储在一个变量中,并一致地引用该变量。