【问题标题】:NSCalendar.components().minute returning inconsistent valuesNSCalendar.components().minute 返回不一致的值
【发布时间】:2015-08-29 14:10:19
【问题描述】:

原来我发帖、测试和代码在下面的链接中遇到的问题 https://stackoverflow.com/questions/27339072/working-with-nsdate-components-in-swift/30822018#30822018

这是最小的测试用例

  1. 我正在创建一个偏离特定日期的日期(本 就像我在 NSDate() 扩展中所做的那样)使用 NSCalendar.dateByAddingUnit(..., value:x, ...)
  2. 然后我使用 NSCalendar.components(..., fromDate, toDate, ....).分钟
  3. 如果 x>0,我在上述步骤中得到的答案是 x-1。如果 x
  4. 这可能会导致应用程序出现错误,这些应用程序使用人类可读属性过滤事件,例如过去 3 小时内的所有事件,因为由于这种行为,180 分钟不是 3 小时。
  5. 这不是步骤 1 中的错误,因为日期打印正确,如图所示 在帖子末尾的打印输出中。

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
    //https://stackoverflow.com/questions/26198526/nsdate-comparison-using-swift


    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) 的结果。寻找*错误。如果您从 sanitizedDate() 中的注释行中删除 cmets,您将得到预期的结果。

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 以获取有关“今天”的输入:

//
//  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
    //https://stackoverflow.com/questions/26198526/nsdate-comparison-using-swift


    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    _________________________

【问题讨论】:

  • 请将相关信息添加到问题本身。输入数据是什么,你得到什么输出,你期望什么?
  • 如果您没有在答案中告诉我们您的确切测试用例(由于“保密原因”),我们如何建议更好的方法?还是我忽略了什么?
  • 即使阅读链接的帖子(其相关部分绝对应包含在此处),我也不清楚问题所在。请edit您的问题更好地解释;示例输入和输出在这里可能会有所帮助。
  • 我编辑了原始帖子以创建最小的测试用例。我不知道为什么我因为没有研究工作而被否决。我在我提到的线程以及这里的帖子中都有大量的代码、测试等。

标签: ios objective-c swift cocoa-touch


【解决方案1】:

您在代码中的 4 个不同位置调用 NSDate()

每个都将返回当前日期和时间该代码执行时,因此它们将相差几分之一秒。

我怀疑您想在整个计算中为“今天”使用一个一致的值。在代码开头调用一次NSDate(),将其存储在一个变量中,并一致地引用该变量。

【讨论】:

  • 就是这样。非常感谢,它防止了未来的错误并简化了我的启动代码。我很不舒服,因为我不得不旋转输入以使其工作,现在已经解决了很好。我将在此处发布接受的代码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-01-28
  • 1970-01-01
  • 1970-01-01
  • 2023-02-08
  • 1970-01-01
  • 1970-01-01
  • 2016-01-27
相关资源
最近更新 更多