calendar_logo

Khi thực hiện chuyển từ chuỗi ký tự sang NSDate và ngược lại, nếu không lưu ý sẽ có thể phát sinh vấn đê do người sử dụng setting calendar trong máy (đặc biệt với các nước sử dụng lịch riêng như Nhật Bản, Trung Quốc v.vv..).

Chuyển từ chuỗi ký tự sang NSDate


Trước hết chúng ta sẽ chia nhỏ chuỗi ký tự ra và gán giá trị cho NSDateComponents, sau đó sẽ tạo biến kiểu NSDate.

NSDateComponents *comps = [[NSDateComponents alloc] init];
    NSDate *date;

    @try {
        [comps setYear: 2012];    // Year
        [comps setMonth:   4];    // Month
        [comps setDay:     1];    // Day
        [comps setHour:   15];    // Hour
        [comps setMinute:  0];    // Minute
        [comps setSecond:  0];    // Second
    }
    @catch (NSException *exception) {
        NSLog(@"error was cought at NSDateComponents set values");
    }
    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSCalendar *gregorianCalendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSGregorianCalendar];
    NSCalendar *japaneseCalendar = [[NSCalendar alloc]initWithCalendarIdentifier:NSJapaneseCalendar];

    date = [calendar dateFromComponents:comps];    // currentCalendar
    NSLog(@"calendar date[%@]", date);

    date = [gregorianCalendar dateFromComponents:comps];    // NSGregorianCalendar
    NSLog(@"gregorianCalendar date[%@]", date);

    date = [japaneseCalendar dateFromComponents:comps];    // NSJapaneseCalendar
    NSLog(@"japaneseCalendar date[%@]", date);

Kết quả như bảng dưới đây:

Gregorian Calendar Japanese Calendar
currentCalendar 2012-04-01 06:00:00 +0000 2012-04-01 06:00:00 +0000
NSGregorianCalendar 2012-04-01 06:00:00 +0000 0024-04-01 06:00:00 +0000
NSJapaneseCalendar 4000-04-01 06:00:00 +0000 2012-04-01 06:00:00 +0000

Nhìn qua thì thấy có vẻ currentCalendar không có vấn đề gì, nhưng nên nhớ khi setting sử dụng Japanese Calendar thì "năm 2012" ở đây là Bình Thành năm 2012 tương đương với năm 4000 đấy nhé (sohai)

Tóm lại, nếu muốn sử dụng NSJapaneseCalendar thì phải nhập số năm tương ứng với lịch Nhật, nếu không sẽ xảy ra sai số ngay.

Chuyển từ NSDate sang chuỗi ký tự


 NSDateFormatter *format;
    NSString *str;

    NSDate *date = [NSDate date];  // lấy current date
    format = [[NSDateFormatter alloc]init];
    [format setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"ja_JP"]];

    [format setDateFormat:@"yyyy-MM-dd"];

    NSCalendar *calendar = [NSCalendar currentCalendar];
    NSCalendar *gregorianCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
    NSCalendar *japaneseCalendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSJapaneseCalendar];

    [format setCalendar:calendar];    // currentCalendar
    str = [format stringFromDate:date];
    NSLog(@"currentCalendar date[%@]", str);

    [format setCalendar:gregorianCalendar];    // NSGregorianCalendar
    str = [format stringFromDate:date];
    NSLog(@"NSGregorianCalendar date[%@]", str);

    [format setCalendar:japaneseCalendar];    // NSJapaneseCalendar
    str = [format stringFromDate:date];
    NSLog(@"japaneseCalendar date[%@]", str);

Kết quả như sau:

Gregorian Calendar Japanese Calendar
currentCalendar 2012-03-31 0024-03-31
NSGregorianCalendar 2012-03-31 2012-03-31
NSJapaneseCalendar 0024-03-31 0024-03-31

Rõ ràng là khi muốn hiển thị cho Gregorian Calendar thì nên sử dụng NSGregorianCalendar, còn khi muốn hiển thị cho Japanese Calendar thì nên sử dụng NSJapaneseCalendar.

currentCalendar khi setting sử dụng Gregorian Calendar thì xử lý như NSGregorianCalendar, khi setting sử dụng Japanese Calendar thì xử lý như NSJapaneseCalendar, tuy nhiên trong trường hợp app sử dụng Gregorian Calendar mà user lại setting sử dụng Japanese thì sẽ xuất hiện lỗi ngay (năm 4000 chả hạn).

Ở các nước Âu Mỹ thì người dùng có lẽ chả thay đổi lịch bao giờ thì sử dụng như currentCalendar thì ko vấn đề, nhưng cần phải hạn chế lỗi này ở các app dành cho thị trường Nhật Bản, Trung Quốc..


Source: iPhoneで和暦表示設定のとき、日付や曜日がずれる