You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift计算日期差值返回0?问题排查求助

问题

我写了一个Swift函数用来判断请假申请日期是否符合公司窗口期规则(提前3个月开放申请,不能预约超过3个月后的假期)。函数接收String类型的申请日期,执行步骤如下:

  • 获取当前日期(A)
  • 将参数日期转为Date类型(B)
  • 计算申请日期往前推3个月的窗口期开放日期(C)
  • 判断C是否晚于当前日期,返回对应提示信息

代码如下:

import Foundation 

func requestLeave(requestedDate: String) -> String {
    
    // GET CURRENT DATE (A)
    let currentDate = Date()
    print("Current Date: \(currentDate.formatted(date: .long, time: .omitted))")
    
    // GET REQUESTED DATE (B)
    // STRING TO DATE 
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd-MM-yyyy"
    guard let requestedDate = dateFormatter.date(from: requestedDate) else { 
        return ("Return some form of error String") 
    }
    
    print("You have requested leave on \(requestedDate.formatted(date: .long, time: .omitted))")
    
    // GET APPLICATION WINDOW OPEN DATE (C)
    // (LEAVE WINDOW OPENS - 3 MONTHS (7890000))
    let windowOpenDate = requestedDate - 7890000 
    print("Applications for leave opens on \(windowOpenDate.formatted(date: .long, time: .omitted))")
    
    if windowOpenDate > currentDate {
        let daysBetween = Calendar.current.dateComponents([.day], from: currentDate, to: windowOpenDate)
        return ("Your leave window opens in \(daysBetween.day ?? 9999) days")
    }
    
    let daysBetween = Calendar.current.dateComponents([.day], from: windowOpenDate, to: currentDate)
    return ("Your leave window opened \(daysBetween.day ?? 9999) days ago!")
}

let request = requestLeave(requestedDate: "10-08-2023")
print(request)

测试时发现,当请求日期为"28-07-2023"和"29-07-2023"时,函数返回"Your leave window opens in 0 days"的错误结果,怀疑是日期的时间部分导致的问题,想确认是否需要剥离时间仅比较日期,以及具体解决方法。


解决方案

问题根源

你的判断完全正确,问题确实出在时间部分的比较上:

  • Date()获取的当前日期包含具体时间(比如当前是2023-04-28 14:30:00)
  • 通过DateFormatter转换的requestedDate默认时间是当天的00:00:00,往前推3个月后的windowOpenDate时间也是00:00:00
  • 当当前时间晚于windowOpenDate的00:00:00时,windowOpenDate > currentDate不成立,但计算天数差时,因为当天已经过了0点,会得到0天的结果,导致错误提示。

另外还有个隐藏问题:用固定秒数7890000来减3个月极不严谨,不同月份天数不同(比如2月28天、3月31天),直接减秒数会导致日期计算不准确。

解决步骤

  1. 剥离时间,仅比较日期部分:用Calendar把所有日期都调整为当天的起始时间(00:00:00)
  2. 用Calendar计算3个月前的日期:避免固定秒数的误差

修改后的代码

import Foundation 

func requestLeave(requestedDate: String) -> String {
    let calendar = Calendar.current
    
    // 获取当前日期并转为当天起始时间(A)
    let currentDate = calendar.startOfDay(for: Date())
    print("Current Date: \(currentDate.formatted(date: .long, time: .omitted))")
    
    // 将参数日期转为Date类型并转为当天起始时间(B)
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd-MM-yyyy"
    guard let requestedDate = dateFormatter.date(from: requestedDate),
          let requestedStartDate = calendar.date(bySettingHour: 0, minute: 0, second: 0, of: requestedDate) else {
        return "无效的日期格式,请输入dd-MM-yyyy格式的日期"
    }
    
    print("You have requested leave on \(requestedStartDate.formatted(date: .long, time: .omitted))")
    
    // 计算申请日期往前推3个月的窗口期开放日期(C),并转为当天起始时间
    guard let windowOpenDate = calendar.date(byAdding: .month, value: -3, to: requestedStartDate),
          let windowOpenStartDate = calendar.startOfDay(for: windowOpenDate) else {
        return "日期计算错误"
    }
    
    print("Applications for leave opens on \(windowOpenStartDate.formatted(date: .long, time: .omitted))")
    
    // 仅比较日期部分
    if windowOpenStartDate > currentDate {
        let daysBetween = calendar.dateComponents([.day], from: currentDate, to: windowOpenStartDate)
        return "你的请假申请窗口将在\(daysBetween.day ?? 9999)天后开放"
    }
    
    let daysBetween = calendar.dateComponents([.day], from: windowOpenStartDate, to: currentDate)
    return "你的请假申请窗口已经开放\(daysBetween.day ?? 9999)天了!"
}

let request = requestLeave(requestedDate: "28-07-2023")
print(request)

关键改进点

  • 用calendar.startOfDay(for:)统一将所有日期转为当天0点,彻底消除时间部分的干扰
  • 用calendar.date(byAdding: .month, value: -3, to:)精确计算3个月前的日期,自动适配不同月份的天数差异
  • 增加了更多可选绑定判断,提升代码的健壮性

内容的提问来源于stack exchange,提问作者OxfordSi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 16:02:49