将flags枚举中表示的天数转换为人类可读日期

时间:2012-05-29 17:04:07

标签: objective-c date enums

// Values of the individual days as powers of two
enum {
    kMonday = 64,
    kTuesday = 32,
    kWednesday = 16,
    kThursday = 8,
    kFriday = 4,
    kSaturday = 2,
    kSunday = 1,
};

将所有127种天数变换为人类可读字符串的最快方法是什么。

例如,如果我得到数字7,我想输出“周五周日”

如果我得到数字66,我想输出“星期一,星期六”

2 个答案:

答案 0 :(得分:3)

基本上你有两个选择:

  • 创建一个工厂,你交出合并日期的整数,然后你就会收回字符串

  • 创建包装器对象,包装int并提供访问内部逻辑的方法

我写了一个包装器:

#import <Foundation/Foundation.h>

typedef NS_OPTIONS(NSUInteger, WeekDays) {
    kMonday     = 1 << 6,
    kTuesday    = 1 << 5,
    kWednesday  = 1 << 4,
    kThursday   = 1 << 3,
    kFriday     = 1 << 2,
    kSaturday   = 1 << 1,
    kSunday     = 1 << 0
};

@interface DaysWrapper : NSObject
-(id)initWithDays:(WeekDays)weekDays;
@end

@interface DaysWrapper ()
@property (nonatomic,retain) NSMutableArray *days;
@end


@implementation DaysWrapper{
    int internalDays;
}

+(instancetype)dayWrapperWithDayBitmask:(WeekDays)daybits
{
    return [[DaysWrapper alloc] initWithDays:daybits];
}

-(instancetype)initWithDays:(WeekDays)weekDays
{
    if (self = [super init]) {
        WeekDays wholeWeek = 127;
        internalDays = weekDays & wholeWeek;
        _days = [@[] mutableCopy];

        while (wholeWeek) {
            wholeWeek >>= 1;
            if (weekDays & (wholeWeek +1)) {
                [_days addObject:[NSNumber numberWithBool:YES]];
            } else {
                [_days addObject:[NSNumber numberWithBool:NO]];
            }
        }
    }
    return self;
}

-(NSString *)description
{
    static dispatch_once_t onceToken;
    static NSArray *dayNames;
    static NSDictionary *fullnamesForDayNames;
    dispatch_once(&onceToken, ^{
        dayNames = @[@"Mon", @"Tues", @"Wend",@"Thu", @"Fri",@"Sat", @"Sun"];
        fullnamesForDayNames = [[NSDictionary alloc] initWithObjects: @[@"Monday",@"Tuesday",@"Wendsday",@"Thursday",@"Friday",@"Saturday",@"Sunday"]
                                                             forKeys:dayNames];
    });


    NSMutableString *returnSting = [@"" mutableCopy];
    __block BOOL previousWasAvailable = NO;
    NSMutableArray *dayRanges = [@[] mutableCopy];
    [self.days enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        if (!previousWasAvailable && [obj boolValue])
            [dayRanges addObject:[@[] mutableCopy]];

        if ([obj boolValue]) {
            NSMutableArray *actualRange = [dayRanges lastObject];
            [actualRange addObject:dayNames[idx]];
        }
        previousWasAvailable = [obj boolValue];
    }];

    [dayRanges enumerateObjectsUsingBlock:^(NSMutableArray *rangeArray, NSUInteger idx, BOOL *stop) {

        if ([returnSting length]){
            [returnSting appendString:@","];
        }

        if ([rangeArray count] > 1) {
            [returnSting appendString: [rangeArray firstObject]];

            if ([rangeArray count] > 2){
                [returnSting appendString:@"-"];
            } else {
                [returnSting appendString:@","];
            }
        }

        if (idx == [dayRanges count]-1){
            [returnSting appendString: fullnamesForDayNames[[rangeArray lastObject]]];
        } else {
            [returnSting appendString:[rangeArray lastObject]];
        }
    }];

    return returnSting;
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {

        WeekDays monAndFriday    = kMonday | kFriday;
        WeekDays thurToSat       = kThursday | kFriday | kSaturday;
        WeekDays weekEnd         = kFriday | kSaturday | kSunday;
        WeekDays mondAndWeekend  = weekEnd | kMonday;
        WeekDays friSat          = kFriday | kSaturday;
        WeekDays everySecondDay  = 8 | 32 | 2;
        WeekDays moday           = kMonday;
        WeekDays workWeek        = kMonday | kTuesday | kWednesday | kThursday | kFriday;
        WeekDays wholeWeek       = workWeek | weekEnd;
        WeekDays notThursday     =  ~kThursday & wholeWeek;

        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:monAndFriday]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:weekEnd]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:thurToSat]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:mondAndWeekend]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:friSat]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:everySecondDay]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:moday]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:workWeek]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:wholeWeek]);
        NSLog(@"%@", [DaysWrapper dayWrapperWithDayBitmask:notThursday]);
    }
    return 0;
}

<强>输出

Mon,Friday
Fri-Sunday
Thu-Saturday
Mon,Fri-Sunday
Fri,Saturday
Tues,Thu,Saturday
Monday
Mon-Friday
Mon-Sunday
Mon-Wend,Fri-Sunday

随意的想法

  • 而不是在数组名称self.days中保存整数信息的副本,您可以在每次需要时动态处理它以减少空间
  • 工厂基本上具有相同的逻辑

通用代码检修(ARC,现代obj-c语法,NS_OPTIONS,...)2015年5月21日

答案 1 :(得分:3)

这是一个有趣的挑战。

#import <Foundation/Foundation.h>
enum {
    kMonday = 1 << 0,
    kTuesday = 1 << 1,
    kWednesday = 1 << 2,
    kThursday = 1 << 3,
    kFriday = 1 << 4,
    kSaturday = 1 << 5,
    kSunday = 1 << 6,
};
typedef int DayBits;

NSString * const shortDayNames[] = { @"Mon", @"Tues", @"Wed", @"Thurs", @"Fri", @"Sat", @"Sun" };
NSString * const fullDayNames[] = { @"Monday", @"Tuesday", @"Wednesday", @"Thursday", @"Friday", @"Saturday", @"Sunday" };


int main(int argc, const char * argv[])
{

    @autoreleasepool {
        // Demo all possible combinations
        for( DayBits days_as_bits = 0; days_as_bits < 128; days_as_bits++ ){
            // Create an index set from the bits
            NSMutableIndexSet * indexes = [NSMutableIndexSet indexSet];
            for( int bit = 0; bit < 7; bit++ ){
                if( days_as_bits & (1 << bit) ){
                    [indexes addIndex:bit];
                }
            }

            // Create string for result
            NSMutableString * daysDesc = [NSMutableString string];
            // Enumerate the index set backwards and build up the string
            __block BOOL contiguous = NO;
            [indexes enumerateIndexesWithOptions:NSEnumerationReverse 
                                      usingBlock:^(NSUInteger idx, BOOL *stop) {
                // Use short names unless this is the name that will appear 
                // at the end of the string
                NSString * const * dayNames = shortDayNames;
                if (0 == [daysDesc length]) {
                    dayNames = fullDayNames;
                }
                // If the previous index is present, we're working on a contiguous set
                if( [indexes containsIndex:(idx - 1)] ){
                    // If we were already in a contiguous set, just continue
                    if( contiguous ){
                        return;
                    }
                    // This is the end day of a contiguous set; place the name 
                    // and a hyphen
                    else {
                        [daysDesc insertString:[NSString stringWithFormat:@"-%@", dayNames[idx]]
                                                                  atIndex:0];
                        contiguous = YES;
                        return;
                    }
                }
                // We've reached the start day of a set. 
                // Turn off contiguous and fall through
                else {
                    contiguous = NO;
                }

                // Place a comma and today's name
                [daysDesc insertString:[NSString stringWithFormat:@", %@", dayNames[idx]]
                                                          atIndex:0];
            }];
            // Clean up extraneous comma and space at the beginning of the string
            daysDesc = [daysDesc stringByTrimmingCharactersInSet:[NSCharacterSet characterSetWithCharactersInString:@" ,"]];
            NSLog(@"%d: %@", days_as_bits, daysDesc);
        }

    }
    return 0;
}

请注意,我已将enum切换为使其正常工作,因此这对您来说实际上可能完全没用,但希望它有用。这意味着,例如,7是kMonday | kTuesday | kWednesday而不是kFriday | kSaturday | kSunday,因此结果为Mon-Wed

我认为使用索引集可能是我必须提供的主要洞察力。

你可能可以通过一些工作来切换回来(不要反转枚举等);我已经浪费了足够的时间^ W ^ W ^ W满足了我对此的好奇心。