How to show year only in NSDatePicker

663 views Asked by At

I want to show year component only in a NSDatePicker.

I tried set/add NSDateFormatter to NSDatePicker, but with no luck. (By dragging a NSDateFormatter to NSDatePicker in nib)

Is there any way to achieve this without subclassing NSDatePicker or NSTextField? Thank you!

3

There are 3 answers

1
Pierre Bernard On BEST ANSWER

-[NSDatePicker setDatePickerElements:] can no longer be tricked into showing year only.

A year-only NSDatePicker can be obtained by configuring a year-month picker and subclassing NSDatePickerCell to prevent it from creating the month and separator fields:

- (void)_addSubfieldForElement:(int)arg1 withDateFormat:(id)arg2 referenceStrings:(id)arg3
{
    if ((arg1 == 6) || (arg1 == 100)) {
        return;
    }

    [super _addSubfieldForElement:arg1 withDateFormat:arg2 referenceStrings:arg3]; // Private API
}

Please file bug reports with Apple to request a year-only variant of NSDatePicker. I also requested a week-of-year picker.

0
GeneCode On

It is easy you don't need to use NSDatePicker. All you have to do is create a range of years you want and use it as datasource for normal picker.

for (int i=1900; i<=currentYear; i++) {
  [_yourDataSourceArr addObject:[NSString stringWithFormat:@"%d",i]];
}
1
Zhigang An On

After diving into Apple's Documentation, I found the solution and want to post it here, in case it is useful for someone else.

No need to subclass NSDatePicker, there is a method - (void)setDatePickerElements:(NSDatePickerElementFlags)elementFlags which specifies which element the date picker would display. elementFlags is a constant, defined by a enum as:

enum {
   NSHourMinuteDatePickerElementFlag       = 0x000c,
   NSHourMinuteSecondDatePickerElementFlag = 0x000e,
   NSTimeZoneDatePickerElementFlag         = 0x0010,
   NSYearMonthDatePickerElementFlag        = 0x00c0,
   NSYearMonthDayDatePickerElementFlag     = 0x00e0,
   NSEraDatePickerElementFlag              = 0x0100,
};
typedef NSUInteger NSDatePickerElementFlags;

When looking at those constants, I find it is just a bit mask. Bit place and the corresponding calendar elements is as follows:

15 - 9 bit: Unknown. Maybe unused.

8 bit: Era. (Would not display anything if has a 4-digit year format.)

7 bit: Year.

6 bit: Month.

5 bit: Day.

4 bit: Time zone.

3 bit: Hour.

2 bit: Minute.

1 bit: second.

0 bit: Unknown. Maybe millisecond, or unused.

So, the following line would give me a year only date picker:

[_yearOnlyDatePicker setDatePickerElements:0x0080];

_yearOnlyPicker is an instance of NSDatePicker.


Here is the result:

How yearOnlyDatePicker looks like in Interface Builder:

In interface builder.

How yearOnlyDatePicker looks like when running the app:

When running the app.