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

Swift获取每月首日功能异常,求问题原因及解决方法

问题原因及解决办法

核心问题:时区不匹配

你的原始日期都是UTC时区(+0000),但Calendar.current默认使用设备的本地时区。当你仅用year和month两个组件生成日期时,Calendar会在本地时区创建当月1日的00:00,转换为UTC时区后就变成了前一天的23:00,所以看起来像是上月末。

举个例子:如果你的设备时区是GMT+1,本地时间的2022-09-01 00:00,对应UTC时间就是2022-08-31 23:00,这就是你看到错误输出的原因。


解决办法1:统一使用UTC时区处理日期

把Calendar和DateFormatter的时区都设置为UTC,确保所有日期处理逻辑在同一个时区下执行:

let dateList = ["2023-01-26 02:30:53 +0000",
                "2022-12-28 09:42:27 +0000",
                "2022-11-09 05:48:42 +0000",
                "2022-09-30 09:08:03 +0000",
                "2022-08-31 10:22:31 +0000",
                "2022-07-29 04:15:02 +0000",
                "2022-06-20 12:57:35 +0000",
                "2022-05-12 15:36:37 +0000",
                "2022-04-18 03:14:29 +0000",
                "2022-03-10 02:40:42 +0000",
                "2022-02-07 18:03:15 +0000",
                "2022-01-18 15:18:24 +0000"]

// 初始化日期格式化器并指定UTC时区
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
dateFormatter.timeZone = TimeZone(identifier: "UTC")

// 创建UTC时区的日历实例
let utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!

for dates in dateList {
    let currentDate = dateFormatter.date(from:dates)!
    let components = utcCalendar.dateComponents([.month, .year], from: currentDate)
    
    // 手动构造当月第一天的组件
    var firstDayComponents = DateComponents()
    firstDayComponents.year = components.year
    firstDayComponents.month = components.month
    firstDayComponents.day = 1
    firstDayComponents.timeZone = TimeZone(identifier: "UTC")
    
    let monthName = utcCalendar.monthSymbols[components.month!-1]
    let year = components.year!
    let month = utcCalendar.date(from: firstDayComponents)!
    
    print("\(currentDate) |||||", "\(month) |||||", "\(components.month!-1) |||||", "\(year) \(monthName)")
}

解决办法2:用Calendar的时间区间方法获取当月首日

使用dateInterval(of:for:)直接获取目标日期所在月份的时间区间,这种方法更可靠,避免手动构造组件的误差:

let dateList = ["2023-01-26 02:30:53 +0000",
                "2022-12-28 09:42:27 +0000",
                "2022-11-09 05:48:42 +0000",
                "2022-09-30 09:08:03 +0000",
                "2022-08-31 10:22:31 +0000",
                "2022-07-29 04:15:02 +0000",
                "2022-06-20 12:57:35 +0000",
                "2022-05-12 15:36:37 +0000",
                "2022-04-18 03:14:29 +0000",
                "2022-03-10 02:40:42 +0000",
                "2022-02-07 18:03:15 +0000",
                "2022-01-18 15:18:24 +0000"]

let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
dateFormatter.timeZone = TimeZone(identifier: "UTC")

let utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!

for dates in dateList {
    let currentDate = dateFormatter.date(from:dates)!
    // 获取当前日期所在月份的时间区间
    guard let monthInterval = utcCalendar.dateInterval(of: .month, for: currentDate) else {
        continue
    }
    let firstDayOfMonth = monthInterval.start
    
    let components = utcCalendar.dateComponents([.month, .year], from: currentDate)
    let monthName = utcCalendar.monthSymbols[components.month!-1]
    let year = components.year!
    
    print("\(currentDate) |||||", "\(firstDayOfMonth) |||||", "\(components.month!-1) |||||", "\(year) \(monthName)")
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.02 12:05:45