【问题标题】:How can I calculate the difference between two dates?如何计算两个日期之间的差异?
【发布时间】:2011-05-21 06:46:09
【问题描述】:

如何计算 2010 年 1 月 1 日和(例如)2010 年 2 月 3 日之间的天数?

【问题讨论】:

    标签: objective-c swift date nsdate


    【解决方案1】:

    在 Swift 5 和 iOS 12 中,根据您的需要,您可以使用以下两种方法之一来查找两个日期之间的天数差异。


    #1。使用CalendardateComponents(_:from:to:)方法

    import Foundation
    
    let calendar = Calendar.current
    
    let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
    let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!
    
    let dateComponents = calendar.dateComponents([Calendar.Component.day], from: startDate, to: endDate)
    
    print(dateComponents) // prints: day: 1621 isLeapMonth: false
    print(String(describing: dateComponents.day)) // prints: Optional(1621)
    

    #2。使用DateComponentsFormatterstring(from:to:)方法

    import Foundation
    
    let calendar = Calendar.current
    
    let startDate = calendar.date(from: DateComponents(year: 2010, month: 11, day: 22))!
    let endDate = calendar.date(from: DateComponents(year: 2015, month: 5, day: 1))!
    
    let formatter = DateComponentsFormatter()
    formatter.unitsStyle = .full
    formatter.allowedUnits = [NSCalendar.Unit.day]
    
    let elapsedTime = formatter.string(from: startDate, to: endDate)
    print(String(describing: elapsedTime)) // prints: Optional("1,621 days")
    

    【讨论】:

      【解决方案2】:

      如果您想要所有单位,而不仅仅是最大的单位,请使用以下两种方法之一(基于@Ankish 的回答):

      示例输出:28 D | 23 H | 59 M | 59 S

      + (NSString *) remaningTime:(NSDate *)startDate endDate:(NSDate *)endDate
      {
          NSCalendarUnit units = NSCalendarUnitDay | NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond;
          NSDateComponents *components = [[NSCalendar currentCalendar] components:units fromDate: startDate toDate: endDate options: 0];
          return [NSString stringWithFormat:@"%ti D | %ti H | %ti M | %ti S", [components day], [components hour], [components minute], [components second]];
      }
      
      + (NSString *) timeFromNowUntil:(NSDate *)endDate
      {
          return [self remaningTime:[NSDate date] endDate:endDate];
      }
      
      

      【讨论】:

        【解决方案3】:

        要查找差异,您需要获取当前日期和将来的日期。在以下情况下,我使用 2 天作为未来日期的示例。计算方式:

        2 days * 24 hours * 60 minutes * 60 seconds。我们预计 2 天内的秒数为 172,800。

        // Set the current and future date
        let now = Date()
        let nowPlus2Days = Date(timeInterval: 2*24*60*60, since: now)
        
        // Get the number of seconds between these two dates
        let secondsInterval = DateInterval(start: now, end: nowPlus2Days).duration
        
        print(secondsInterval) // 172800.0
        

        【讨论】:

        • 请不要只发布代码作为答案,还要解释您的代码的作用以及它如何解决问题的问题。带有解释的答案通常质量更高,更有可能吸引投票。
        【解决方案4】:

        斯威夫特 4
        试试这个看看(带字符串的日期范围):

        // Start & End date string
        let startingAt = "01/01/2018"
        let endingAt = "08/03/2018"
        
        // Sample date formatter
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "dd/MM/yyyy"
        
        // start and end date object from string dates
        var startDate = dateFormatter.date(from: startingAt) ?? Date()
        let endDate = dateFormatter.date(from: endingAt) ?? Date()
        
        
        // Actual operational logic
        var dateRange: [String] = []
        while startDate <= endDate {
            let stringDate = dateFormatter.string(from: startDate)
            startDate = Calendar.current.date(byAdding: .day, value: 1, to: startDate) ?? Date()
            dateRange.append(stringDate)
        }
        
        print("Resulting Array - \(dateRange)")
        

        斯威夫特 3

        var date1 = Date(string: "2010-01-01 00:00:00 +0000")
        var date2 = Date(string: "2010-02-03 00:00:00 +0000")
        var secondsBetween: TimeInterval = date2.timeIntervalSince(date1)
        var numberOfDays: Int = secondsBetween / 86400
        print(numberOfDays)
        

        【讨论】:

        • 并非所有日子都有这么多的秒数。
        • @Pavan - 欢迎您通过更新此答案来分享您的意见并使其变得更好。
        • 为了让它变得更好,我需要重写你的整个答案,在这种情况下,它也可以被删除,因为它与上面不使用硬编码值的答案相同:)
        【解决方案5】:

        看看这个。它处理夏令时、闰年,因为它使用 iOS 日历进行计算。您可以将字符串和条件更改为包括小时和天的分钟。

        +(NSString*)remaningTime:(NSDate*)startDate endDate:(NSDate*)endDate
        {
            NSDateComponents *components;
            NSInteger days;
            NSInteger hour;
            NSInteger minutes;
            NSString *durationString;
        
            components = [[NSCalendar currentCalendar] components: NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute fromDate: startDate toDate: endDate options: 0];
        
            days = [components day];
            hour = [components hour];
            minutes = [components minute];
        
            if(days>0)
            {
                if(days>1)
                    durationString=[NSString stringWithFormat:@"%d days",days];
                else
                    durationString=[NSString stringWithFormat:@"%d day",days];
                return durationString;
            }
            if(hour>0)
            {        
                if(hour>1)
                    durationString=[NSString stringWithFormat:@"%d hours",hour];
                else
                    durationString=[NSString stringWithFormat:@"%d hour",hour];
                return durationString;
            }
            if(minutes>0)
            {
                if(minutes>1)
                    durationString = [NSString stringWithFormat:@"%d minutes",minutes];
                else
                    durationString = [NSString stringWithFormat:@"%d minute",minutes];
        
                return durationString;
            }
            return @""; 
        }
        

        【讨论】:

        • 这个方法是计算时差的完美方法。
        • 只是你可以保留 elseif 与所有那些 if 条件。否则您将只显示一种格式的时间。
        【解决方案6】:

        您可以通过以秒为单位转换日期并为此取自 1970 年以来的时间间隔来找到差异,然后您可以找到两个日期之间的差异。

        【讨论】:

        • 当两个日期可以直接相互计算时(假设时域相同)。首先计算自 1970 年以来的两个日期然后找出差异有什么具体原因吗?
        【解决方案7】:
        NSDate *date1 = [NSDate dateWithString:@"2010-01-01 00:00:00 +0000"];
        NSDate *date2 = [NSDate dateWithString:@"2010-02-03 00:00:00 +0000"];
        
        NSTimeInterval secondsBetween = [date2 timeIntervalSinceDate:date1];
        
        int numberOfDays = secondsBetween / 86400;
        
        NSLog(@"There are %d days in between the two dates.", numberOfDays);
        

        编辑:

        请记住,NSDate 对象代表确切的时刻,它们没有任何关联的时区信息。当您使用例如将字符串转换为日期时NSDateFormatterNSDateFormatter 从配置的时区转换时间。因此,两个NSDate 对象之间的秒数将始终与时区无关。

        此外,this documentation 指定 Cocoa 的时间实现不考虑闰秒,因此如果您需要这样的精度,则需要滚动您自己的实现。

        【讨论】:

        • @RalucaGurau:86400 是一天中的秒数(即 60 秒,乘以 60 分钟,乘以 24 小时)。它与月份无关。
        • 并非所有日子都有 86400 秒。对于一个微不足道的例子,这很好,但在现实世界中这不是一个好主意。 DST 变化、闰秒等都可能与它混淆。 NSCalendar 可以告诉您一天中有多少秒。
        • @muthukumar:不适用于 iOS,该方法仅适用于 Mac OS X。此问题标记为 cocoa 而不是 cocoa-touch,因此此答案仅适用于 Mac OS X。
        • 任意两个时间点之间的天数总是86400。人类是否处于自欺欺人的阶段,比平时早起一个小时,这与一个事实没有区别。一天是 86400 秒长(忽略闰秒)
        • 只想补充一点,如果你最后没有那个 +0000,那么无论如何你都会得到空日期和 0 的值。所以,不要掉进那个陷阱。
        【解决方案8】:

        你可能想使用这样的东西:

        NSDateComponents *components;
        NSInteger days;
        
        components = [[NSCalendar currentCalendar] components: NSDayCalendarUnit 
                fromDate: startDate toDate: endDate options: 0];
        days = [components day];
        

        我相信这种方法可以解决诸如日期跨越夏令时变化之类的情况。

        【讨论】:

        • 有没有一种简单的方法也可以忽略给定日期的时间?
        • 可以针对其他日历单位进行相应更改:) 用于年份单位。
        • NSDate 对象已经与时区无关。解析日期时会删除时区信息,例如NSDateFormatter,这样NSDate 对象就代表了准确的时刻。因此,如果您已经拥有startDateendDate,这两个对象将相隔 x 秒数。时区与它无关。
        • @Benjamin:你为什么这么说?
        • dreamlax,你的答案是错误的。干净利落。计算标准时间 1 月 1 日中午 12 点和 4 月 1 日中午 12 点之间的天数,您的公式不起作用。这是一个惰性公式,开发人员应该使用 NSDateComponents 对象来计算它。
        【解决方案9】:
        NSTimeInterval diff = [date2 timeIntervalSinceDate:date1]; // in seconds
        

        其中date1date2NSDate

        另外,注意NSTimeInterval的定义:

        typedef double NSTimeInterval;
        

        【讨论】:

        • 请注意,NSTimeInterval 确实是一个双精度数,因此您可以像使用任何其他数字一样使用它。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-02-01
        • 1970-01-01
        • 2021-11-25
        • 2011-08-01
        • 1970-01-01
        相关资源
        最近更新 更多