NSDateFormatter relative date formatting with custom format

前端 未结 3 2350
再見小時候
再見小時候 2021-02-19 23:18

So my intention is to put out dates that would look like the following:

Today, August 28
Tomorrow, August 29
Friday, August 30
...etc

The issue

3条回答
  •  抹茶落季
    2021-02-20 00:14

    It seems there is no way to accomplish this kind of date formatting without going into a custom implementation. So, the short answer to this question is 'No'.

    However, the problem still exists, so below is my own solution to the problem.

    Make a subclass of NSDateFormatter and implement custom init and override stringFromDate: method.

    - (instancetype)initWithDateFormat:(NSString *)dateFormat
    {
        self = [super init];
        if (self) {
            NSLocale *locale = [NSLocale currentLocale];
            self.locale = locale;
    
            self.timeStyle = NSDateFormatterNoStyle;
            self.dateStyle = NSDateFormatterShortStyle;
            self.doesRelativeDateFormatting = YES;
    
            self.dateFormat = dateFormat;
        }
        return self;
    }
    
    - (NSString *)stringFromDate:(NSDate *)date
    {
        NSString *dateFormat = self.dateFormat;
        self.dateFormat = nil;
    
        BOOL didRelativeDateFormatting = self.doesRelativeDateFormatting;
        self.doesRelativeDateFormatting = YES;
    
        NSString *result = [super stringFromDate:date];
    
        if ([result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != NSNotFound) {
            self.dateFormat = dateFormat;
            self.doesRelativeDateFormatting = NO;
            result = [super stringFromDate:date];
        }
    
        self.dateFormat = dateFormat;
        self.doesRelativeDateFormatting = didRelativeDateFormatting;
    
        return result;
    }
    

    Since doesRelativeDateFormatting and dateFormat are mutually exclusive we try to use relative formatting first. Given that we set self.dateStyle = NSDateFormatterShortStyle in the init method, we know the date will contain decimal numbers unless it is replaced with words meaning 'today', 'tomorrow' and anything that may appear in other languages. If we did not spot any numbers we accept this result.

    If there are digital numbers in the string we assume the relative formatting did not happen, so we apply our own date format.

提交回复
热议问题