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
相关产品推荐
相关产品推荐

