Trying to understand NSDatePicker

374 Views Asked by At

I'm desperately trying to understand swift's DatePicker. I have a need to select dates from Julian Day 0 (11/24/4714 BCE) to dates in the future. When I extract the DateComponents from the DatePicker, they do not appear to be a 'proleptic' gregorian calendar. For instance, by selecting 3/1/300 AD (or CE), the month and day are 2/29. This seems consistent with the Julian Calendar, a date I cannot select with the DatePicker's calendar set to iso8601 or gregorian. I am familiar with the date of adoption of the Gregorian calendar, and indeed this is where the discrepancies begin. But why won't it calculate the proleptic dates, or am I misunderstanding this. Extracting these components is necessary for calculating various quantities such as Julian Day or converting from one calendar to another. Even a suggestion of where to find the info would be appreciated.

---Edited to show code -----

@IBAction func calculate(_ sender: Any) {
    var mycal = Calendar(identifier: .iso8601)
    //var mycal = Calendar(identifier: .gregorian)
    let picked_date:Date = datePicker.dateValue
    let formatter1 = DateFormatter()
    formatter1.locale = Locale(identifier: "en_US_POSIX")
    formatter1.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZZZZZ"
    let picked_format = formatter1.string(from: picked_date)
    //print("picked_format: \(picked_format)")
    let format_date = formatter1.date(from: picked_format)
    var tz: String { return TimeZone.current.identifier }
    let myzone = UTC.state == NSOnState ? tz : "GMT"
    //let era = AD.state == NSOnState ? 1 : 0
    mycal.timeZone = TimeZone(identifier: myzone)!
    var comps = mycal.dateComponents([.year,
                                    .month,
                                    .day,
                                    .hour,
                                    .minute,
                                    .second,
                                    //.era,
                                    //.nanosecond,
                                    .timeZone],
                                from: format_date!)
    print(comps.month!)
    print(comps.day!)
1

There are 1 best solutions below

0
Aloft On

Bottom line: The discrepancies in what was shown in DatePicker vs the 'elements' of the date object it produced (namely, YEAR, MONTH and DAY) were due wholly to a careless mistake I made writing the code: The failure to ensure that all the objects that dealt with dates were specified to the same Calendar. Initially, my DateFormatter and DateComponents objects were set to ".iso8601" and failing to specify a calendar for the DatePicker defaulted it to my locale, which meant ".gregorian". This produced a 10 day discrepancy in the date prior to Oct 15, 1582. Also: A DatePicker using the Gregorian calendar will allow you to select days from 5 Oct 1582 - 14 Oct 1582 (inclusive), just as I would expect from a proleptic calendar. A DatePicker using the ISO calendar will NOT allow dates in this range. Stepping down from 15 Oct 1582 by one day will result in the DatePicker showing 4 Oct 1582 ... not the result I would expect if it is based on the proleptic Gregorian.

Some caveats, though. Apple's documentation and the ISO standard itself lead me to believe that the ISO calendar was based on a proleptic Gregorian calendar. This proved to be untrue. You can repeat for yourself the following: Create a DatePicker specifying the ISO calendar and it will allow you to choose dates which do not exist in the Gregorian calendar, namely leap years for such years as 1500, 1400, 1300, 1100, 1000, etc. This is more in keeping with the ISO calendar behaving like the Julian Calendar prior to the adoption date. Indeed, the date discrepancies begin to narrow as the year number decreases because the ISO calendar is counting those years as leap years. The error becomes ZERO from 1 March 200 - 28 Feb 300 AD, exactly as one would expect of a Julian Calendar vs a proleptic Gregorian calendar. I don't know if I am misunderstanding how the ISO calendar is supposed to behave, or if this is a bug. Thanks to Willeke for leading me to the correct solution!