Format date time bằng NSDateFormatter

NSDateFormatter


Khai báo NSDateFormatter

    NSDateFormatter *formatter = [NSDateFormatter new];
    [formatter setLocale:[NSLocale systemLocale]];
    [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"VNT"]];
    [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
    [formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]];
    [formatter setDateFormat:@"hh:mm"];

Sau khi sử dụng đoạn code trên, output sẽ là giờ-phút có định dạng 12h, chứ ko phải là định dạng 24h như mong muốn.

Nguyên nhân là setting NSLocale bị sai ? hay là do NSTimeZone có vấn đề ?

Thực ra, lý do là hh sẽ trả lại thời gian theo định dạng 12h, còn HH sẽ trả lại thời gian theo định dạng 24h 😄

    [formatter setDateFormat:@"hh:mm"];// định dạng 12h
    [formatter setDateFormat:@"HH:mm"];// định dạng 24h

Date format list


Format của setDateFormat được căn cứ theo Unicode format.

Field Symbol No. Example Description
Year y 1..n 2015 Năm. Thông thường thì số ký tự để quy định zero-padding, chỉ duy nhất trường hợp khai báo yy là quy định số ký tự tối đa.

Ví dụ:

Year y yy yyy yyyy yyyyy
AD 1 1 01 001 0001 00001
AD 12 12 12 012 0012 00012
AD 123 123 23 123 0123 00123
AD 1234 1234 34 1234 1234 01234
AD 12345 12345 45 12345 12345 12345

Các trường khác hay gặp:

Field Symbol No. Example Description
Year Y 1..n 2015 Hiển thị năm tính theo ISO year-week calendar (※1). Có thể sẽ khác với lịch bình thường
Month M 1..2 06 Hiển thị chữ số của tháng tương ứng
Month M 3 Jun Hiển thị text rút gọn của tháng tương ứng
Month M 4 June Hiển thị text đầy đủ của tháng tương ứng
Month M 5 J Hiển thị text bị giới hạn của tháng tương ứng
Week w 1..2 27 Hiển thị số thứ tự trong năm của tuần tương ứng
Week W 1 3 Hiển thị số thứ tự trong tháng của tuần tương ứng
Hour h 1..2 11 Hiển thị giờ theo định dạng 12h [1-12]
Hour H 1..2 13 Hiển thị giờ theo định dạng 24h [0-23]
Minute m 1..2 59 Hiển thị phút theo 1..2 ký tự (zero padding)
Second s 1..2 12 Hiển thị giây theo 1..2 ký tự (zero padding)
Second S 1..n 5678 Hiển thị phần trăm của giây theo 1..n ký tự

Code ví dụ:

#import <Foundation/Foundation.h>

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSString *str;
        NSDate *date = [NSDate date];
        NSDateFormatter *formatter = [NSDateFormatter new];

        [formatter setLocale:[NSLocale systemLocale]];
        [formatter setTimeZone:[NSTimeZone timeZoneWithAbbreviation:@"VNT"]];
        [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@"en_US_POSIX"]];
        [formatter setCalendar:[[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian]];

        [formatter setDateFormat:@"YYYY-MMM-dd hh:mm:ss"];
        str = [formatter stringFromDate:date];
        NSLog(@"[%@]", str); // output: 2015-Jun-26 02:41:30

        [formatter setDateFormat:@"yy-MMMMM-dd HH:mm:ss.SSS"];
        str = [formatter stringFromDate:date];
        NSLog(@"[%@]", str); // output: 15-J-26 14:41:30.352
    }
    return 0;
}

*1 :

ISO year-week calendar sẽ có nhiều trường hợp sai khác với lịch bình thường sử dụng bên ngoài.

Theo định nghĩa trên Wikipedia, tuần đầu tiên trong năm là tuần có chứa ngày thứ 5 đầu tiên.

Như vậy, sẽ có những trường hợp những ngày đầu tiên trong năm nhưng lại không được tính là ngày của tuần đầu năm mới, mà bị tính là ngày của tuần cuối năm trước.

    // Với trường hợp 2010/01/03 (chủ nhật)
    [formatter setDateFormat:@"YYYY-Www-D"];
    str = [formatter stringFromDate:date];
    NSLog(@"[%@]", str); // output: 2009-W53-7

Ngược lại, sẽ có những trường hợp những ngày cuối cùng trong năm nhưng không được tính là ngày của tuần cuối, mà bị tính là ngày của tuần đầu năm sau.

    // Với trường hợp 2008/12/29 (thứ hai)
    [formatter setDateFormat:@"YYYY-Www-D"];
    str = [formatter stringFromDate:date];
    NSLog(@"[%@]", str); // output: 2009-W01-1

References


NSDateFomatterのUnicode形式一覧

ISO 8601