Note: Bug reported to Apple
Radar number: 29265429 (Link)
I am using a UIDatePicker. When I give Gregorian calendar it works fine. The days starts from 1 to 31
However, when I give it Islamic islamicUmmAlQura
it gives me a strange behaviour. The days starts from 1 to 30 but there is a '2' above 1 and below 30 such that days are as follows 2,1,2,3,4 ... 30
I have created a new empty iOS project and placed the following code into the viewDidLoad
method:
let picker = UIDatePicker(frame: CGRect(x: 0, y: 30, width: 0, height: 0))
picker.datePickerMode = .date
picker.date = Date()
picker.calendar = Calendar(identifier: .islamicUmmAlQura)
picker.autoresizingMask = UIViewAutoresizing.flexibleRightMargin
picker.frame.size.width = 300
view.addSubview(picker)
Screenshot:
It is not that hard to make your own UIPicker that looks like a UIDatePicker, but you have to be careful because the bug is in NSCalendar
as well as NSDatePicker
.
Just to be clear the extra '2' is not selectable, just like 30 is not selectable in a short month. NSDatePicker does not hide invalid days or months, but makes them unselectable. So in the Gregorian calendar if you select February you will still see 29, 30, and 31, but trying to select them the picker will got to 28. The DataPicker figures out how many months and days to show by calling maximumRangeOfUnit:
on the calendar. In an Islamic calendar the correct maximum is {1, 30}, but NSCalendar
returns {1,31} for maximumRangeOfUnit:NSCalendarUnitDay
for all Islamic calendars.
So there are two bugs. One is that NSCalendar is saying that there can be 31 days in an Islamic Month (which I don't believe is true), and the second issue is that NSDatePicker
is showing the 31st day a 2 instead of 31.
Making your own NSDatePicker
is really not that hard. The amount of element in each component is always the same (just make sure to manually set 30 for the days and not use the value from NSCalendar). The tricky part is deciding if a date is invalid and showing the element as gray and not letting the picket rest on it. You can use rangeOfUnit:InUnit:forDate
to get the number of days in a month or number of months in a year. If an invalid element get selected them move the value down to the highest valid date (ie if a user selects 30 in a month with 29 days select 29).
Once a row is selected you can convert from day-month-year to an NSDate with dateFromComponents
on NSCalendar.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With