calendar.date(bySetting: .day, value: 1, of: Date()) wrongly always adding one month

不羁岁月 提交于 2020-07-21 23:06:26

问题


I want to get two dates, the first and last day of current month. Pretty simple. But date(bySetting: Calendar.Component, value: Int, of: Date) are not working properly.

Look this piece of code:

When Date() prints 2019-04-18 14:11:36 UTC

let calendar = Calendar.current

let firstDayDate = calendar.date(bySetting: .day, value: 1, to: Date())! //2019-05-01 03:00:00 UTC  

let firsDayNextMonth = calendar.date(byAdding: .month, value: 1, to: firstDayDate)! //2019-06-01 03:00:00 UTC   
let lastDayMonthDate = calendar.date(bySetting: .day, value: -1, to: firsDayNextMonth)! //2019-05-31 03:00:00 UTC   

Look at firstDayDate value, day value are setted to 1, but get added 1 to month value.

Please tell me if i forgot something, but for me it looks like a bug

Obs: I now i can do that using DateComponent, but if it's a bug, i want to file a bug to apple.

Edit1: I'm not asking how to get the first and last day of current month. I know how to do that using other methods, but how i explain ahead, i think there's a bug in date(byAdding: Calendar.Component, value: Int, to: Date) method or if i'm not using that properly.


回答1:


Well, since i got that this issue it's not necessarily a real bug on method, but it's the way they are setting the component, searching the first forward, and not really setting, on my perception the method name, description and documentation don't reflect the real feature of the method:

They use a example:

So for the “set to Thursday” example, find the Thursday in the Week in which the given date resides (which could be a forwards or backwards move, and not necessarily the nearest Thursday).

But they recommend to use other method to get more control of the behavior:

For more control over the exact behavior, use nextDate(after:matching:matchingPolicy:behavior:direction:).

So, here is the implementation using this recommended method:

let componentDay = DateComponents(day: 1)
let calendar = Calendar.current

let firstDayDate = calendar.nextDate(after: Date(), matching: componentDay, matchingPolicy: .previousTimePreservingSmallerComponents, direction: .backward)!


let firsDayNextMonth = calendar.date(byAdding: .month, value: 1, to: firstDayDate)!
let lastDayMonthDate = calendar.date(byAdding: .day, value: -1, to: firsDayNextMonth)!


来源:https://stackoverflow.com/questions/55748255/calendar-datebysetting-day-value-1-of-date-wrongly-always-adding-one-m

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!