0

There are similar questions but all of them about adding integer number of days to date. But what if I need to add 0.5 day for example?

In other words the following code won't work

let days: Double = 0.5
let date = Calendar.current.date(byAdding: .day, value: days, to: Date())

because:

public func date(byAdding components: DateComponents, to date: Date, wrappingComponents: Bool = false) -> Date?
public func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = false) -> Date?

public struct DateComponents : ReferenceConvertible, Hashable, Equatable, Sendable {
...
public init(calendar: Calendar? = nil, timeZone: TimeZone? = nil, era: Int? = nil, year: Int? = nil, month: Int? = nil, day: Int? = nil, hour: Int? = nil, minute: Int? = nil, second: Int? = nil, nanosecond: Int? = nil, weekday: Int? = nil, weekdayOrdinal: Int? = nil, quarter: Int? = nil, weekOfMonth: Int? = nil, weekOfYear: Int? = nil, yearForWeekOfYear: Int? = nil)
...
}

int values everywhere only

Gargo
  • 1,135
  • 1
  • 10
  • 21
  • Is this simply for converting even fractions of an hour or do you want to handle other values as well, that is convert to hours, minutes, seconds, ...? – Joakim Danielson Jul 19 '23 at 13:09
  • @JoakimDanielson I need to generate an array of dates with double "step" which may be bigger or lower than 1 day. And in my case it is more convenient to use decimal "day count" – Gargo Jul 19 '23 at 13:26

1 Answers1

1

The Calendar class's calendrical calculations like date(byAdding:to:wrappingComponents:) are written to handle lots of different edge cases like leap years, transitions between daylight savings and standard time, etc.

Allowing fractional units would introduce ambiguity to such functions and might make them unreliable in certain edge cases. (e.g. on a day that includes a transition from standard time to daylight standard time, what is .5 day? 12 hours? (24+2)/2 or 13 hours?

If you add 12 integer hours to a Date, the Calendar object can return a result that handles that specific case and is correct. Adding half-a-day the answer is "it depends".

Edit:

I would suggest factoring your code so that you can express the amount you need to add to a Date as an Integer CalendarComponent unit (e.g. hours or minutes for 1/2 day) and then still use the Calendar method date(byAdding:value:to:wrappingComponents:) to add integer units to your Date. It is very likely that there are edge cases that the Calendar class handles that you will miss if you try to do the calculations yourself.

"Calendrical calculations" are messy and full of edge cases. Apple's Calendar class is rich, robust, and well tested. It is likely to handle edge cases that don't even occur to most of us.

Duncan C
  • 128,072
  • 22
  • 173
  • 272
  • So currently I manually convert decimal days to integer seconds to perform such calculations but it is strange that system `Calendar` can't help me in that – Gargo Jul 19 '23 at 13:30
  • Does your code handle the case where the Date to which you are adding 1/2 day is a standard time to daylight savings time day, so the day actually has 25 hours? What about days with leap seconds added? What should you do in those cases? Apple, as the creator of the framework, has to handle everything we throw at it, and fractional units makes that all but impossible. – Duncan C Jul 19 '23 at 16:47
  • leap seconds are ok. Could you please explain "25 hours"? – Gargo Jul 20 '23 at 06:49
  • A day that contains a transition from daylight savings time to standard time, the clock goes from 2:00 am back to 1:00 AM again. Thus that calendar day is actually 25 hours long. – Duncan C Jul 20 '23 at 13:43
  • I am just using that as an example. There are tons of edge cases in calendrical calculations that are very hard to account for. Limiting date component values to integers allows the Calendar class to identify and handle those edge cases. If it allowed fractional date component values the number of edge cases would be very hard to track. – Duncan C Jul 20 '23 at 13:46
  • See the edit to my answer. I suggest you find a CalendarComponent unit that allows you to express your day fractions as integers, and still call the Calendar function `date(byAdding:value:to:wrappingComponents:)`. – Duncan C Jul 28 '23 at 13:02
  • I'll try it in future. Currently the most suitable unit for me is seconds in this case. – Gargo Jul 28 '23 at 14:11