Tìm hiểu về lớp NSDate trong iOS
NSDate là một class được các lập trình viên sử dụng rất nhiều khi viết ứng dụng để làm việc với các dữ liệu date time. Được Apple giới thiệu từ những ngày đầu tiên hệ điều hành iOS ra đời, NSDate là class không thể thiếu trong khi lập trình, bởi tất cả các ứng dụng dù lớn hay nhỏ đều ít nhiều liên ...
NSDate là một class được các lập trình viên sử dụng rất nhiều khi viết ứng dụng để làm việc với các dữ liệu date time. Được Apple giới thiệu từ những ngày đầu tiên hệ điều hành iOS ra đời, NSDate là class không thể thiếu trong khi lập trình, bởi tất cả các ứng dụng dù lớn hay nhỏ đều ít nhiều liên quan đến việc sử dụng ngày tháng hoặc thời gian.
Khi làm việc với dữ liệu thời gian trong iOS, từ những việc đơn giản như format thời gian sang kiểu String, tới những việc phức tạp như so sánh, tính toán các giá trị thời gian với nhau, mọi công việc điều được thực hiện với NSDate và các lớp tiện ích của NSDate.
Những việc thông thường lập trình viên phải làm với dữ liệu thời gian là:
- tạo một string từ đối tượng NSDate với một format ngày tháng nhất định
- So sánh thời gian, ngày tháng của các đối tượng NSDate
- Tính toán thời gian giữa 2 đối tượng NSDate
- Tách NSDate ra thành các thành phần: ngày, tháng, năm, giờ, phút, giây,...
- ...
Đối với những người mới làm quen với iOS, việc sử dụng NSDate có thể là một việc khá rắc rối. Nhưng để nắm bắt được NSDate là một việc không hề khó khăn, chỉ cần hiểu về lớp NSDate, chúng ta sẽ thấy NSDate là một lớp rất tuyệt vời, nó hỗ trợ lập trình viên rất nhiều hàm tiện ích để chúng ta làm việc với dữ liệu ngày tháng một cách đơn giản và dễ dàng
Trong bài này, tôi xin giới thiệu đến bạn đọc lớp NSDate và các lớp tiện ích liên quan, những công việc NSDate có thể làm mà các lập trình viên hay dùng.
1. Những khái niệm cơ bản về NSDate
Trước tiên, chúng ta cần nói về bản thân lớp NSDate. Lớp NSDate là lớp bao gồm thời gian và ngày tháng, NSDate chứa thông tin đồng thời cả ngày tháng và thời gian. Điều này có nghĩa là khi chúng ta làm việc với hoặc thời gian, hoặc ngày tháng, hoặc cả 2, chúng ta cần làm việc với NSDate. hãy tưởng tượng rằng ngày tháng và thời gian là các thuộc tính của NSDate.
Khái niệm format thời gian không được sử dụng lên bản thân NSDate. Ví dụ, khi muốn format thời gian để hiển thị ra màn hình, chúng ta tạo format cho string hiển thị, nhưng format đó chỉ ảnh hưởng đến string đó mà không ảnh hưởng đến đối tượng NSDate
2. Chuyển đổi qua lại giữa NSDate và String
a. Tạo String từ NSDate
Để tạo một string từ đối tượng NSDate, chúng ta sử dụng lớp NSDateFormatter để format việc hiển thị thời gian về một format nhất định
let dateFormatter = NSDateFormatter()
set location cho đối tượng NSDateFormatter (mặc định đối tượng NSDateFormatter sẽ lấy location hiện tại của thiết bị khi không được gán giá trị)
dateFormatter.locale = NSLocale(localeIdentifier: "el_GR")
Sử dụng date formatter styles để format output string
Trong iOS, hệ điều hành đã cung cấp cho chúng ta một số style khác nhau để sử dụng cho NSDateFormatter thông qua Enum NSDateFormatterStyle.
NSDateFormatterStyle có thể nhận các giá trị: case NoStyle, ShortStyle, MediumStyle, LongStyle, FullStyle
dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
Khi được set location và style, Date formater sẽ format ngày tháng theo location và style như chúng ta muốn. Ví dụ đoạn code sau:
let currentDate = NSDate() let dateFormatter = NSDateFormatter() dateFormatter.locale = NSLocale.currentLocale() dateFormatter.dateStyle = NSDateFormatterStyle.FullStyle var convertedDate = dateFormatter.stringFromDate(currentDate) print(convertedDate)
Output:
Sunday, November 22, 2015
Format output string tùy ý
Khi sử dụng NSDateFormatterStyle ở trên, chúng ta không thể thay đổi format của output theo ý muốn của mình. Vì thế, lớp NSDateFormatter cung cấp cho chúng ta khả năng tự tạo Format cho output theo tùy ý muốn của lập trình viên.
Việc sử dụng custom format rất đơn giản, chúng ta chỉ cần cung cấp cho NSDateFormatter một format đúng. Để format đúng, chúng ta cần biết về những ký hiệu sau:
- EEEE: tên đầy đủ của ngày trong tuần (monday, tuesday,...). khi muốn sử dụng viết tắt của ngày, chúng ta sử dụng 1-3 ký tự (ví dụ: EEE sẽ hiển thị mon, tue,...)
- MMMM: tên đầy đủ của tháng (october, november,...). Tương tự, chúng ta sử dụng 1-3 ký tự để hiển thị tháng viết tắt
- dd: ngày của tháng (08, 13, 25,...)
- yyyy: hiển thị năm với 4 chữ số (1990, 2015,...)
- HH: hiển thị giờ với 2 chữ số
- mm: hiển thị phút với 2 chữ số
- ss: hiển thị giây với 2 chữ số
- zzz: hiển thị timezone với 3 chữ cái (GMT,...)
- GGG: hiển thị trước hoặc sau công nguyên (BC, AD)
Ví dụ, để format giống với NSDateFormatterStyle.FullStyle ở ví dụ bên trên, chúng ta làm như sau:
let currentDate = NSDate() let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "EEEE, MMMM dd, yyyy" var convertedDate = dateFormatter.stringFromDate(currentDate) print(convertedDate)
trong ví dụ này, out của chúng ta so với ví dụ bên trên là không đổi như sau:
Output:
Sunday, November 22, 2015
Ví dụ date format có cả thời gian và ngày tháng như sau:
let currentDate = NSDate() let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "dd/MM/yyyy HH:mm" var convertedDate = dateFormatter.stringFromDate(currentDate) print(convertedDate)
Kết quả:
22/11/2015 18:23
b. Tạo NSDate từ String
Trong lớp NSDateFormatter, chúng ta có hàm dateFromString() để tạo đối tượng NSDate từ 1 date String cho trước. Để có thể convert được từ String sang NSDate, chúng ta cần cung cấp cho đối tượng NSDateFormatter dateFormat của String đó. Ví dụ:
let dateString = "Sun, 22 Nov 2015 18:25:44 GMT" let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = "EEE, dd MMM yyyy HH:mm:ss zzz" let newDate = dateFormatter.dateFromString(dateAsString)
Trong ví dụ trên, chúng ta sẽ tạo được ra 1 đối tượng NSDate với các thông tin về ngày tháng, thời gian ứng với string dateString
Chú ý, khi chuyển từ string về NSDate, chúng ta có thể nhận được thời gian khác với thời gian trong string. Điều này là bình thường vì trong chuỗi dateString ở trên, chúng ta lấy timeZone là GMT, trong khi đó máy của chúng ta thường để timezone là timeZone của chúng ta
3. Sử dụng NSDateComponents
Trong khi lập trình, có nhiều lúc lập trình viên chỉ muốn lấy ra giá trị của một phần của NSDate như ngày, tháng hoặc giờ, phút. Để làm được việc này, chúng ta cần sử dụng lớp NSDateComponents
Khi muốn chuyển đổi giữa NSDate và NSDateComponents, chúng ta cần sử dụng thêm lớp NSCalendar. Lớp NSCalendar là lớp thực hiện việc biến đổi từ NSDate thành NSDateComponents và ngược lại
a. Tạo đối tượng NSDateComponents từ đối tượng NSDate
Để cho dễ hình dung việc tạo NSDateComponents từ NSDate, chúng ta hãy nhìn vào ví dụ sau:
// 1 let currentDate = NSDate() // 2 let calendar = NSCalendar.currentCalendar() // 3 let dateComponents = calendar.components([NSCalendarUnit.Day, NSCalendarUnit.Month, NSCalendarUnit.Year, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Hour, NSCalendarUnit.Minute, NSCalendarUnit.Second, NSCalendarUnit.Nanosecond], fromDate: currentDate) // 4 print("day = (dateComponents.day)", "month = (dateComponents.month)", "year = (dateComponents.year)", "week of year = (dateComponents.weekOfYear)", "hour = (dateComponents.hour)", "minute = (dateComponents.minute)", "second = (dateComponents.second)", "nanosecond = (dateComponents.nanosecond)" , separator: ", ", terminator: "")
Trong ví dụ trên:
- 1: tạo đối tượng NSDate là thời gian hiện tại của thiết bị
- 2: tạo đối tượng NSCalendar là calendar hiện tại
- 3: tạo đối tượng NSDateComponents. Như chúng ta thấy trong đoạn code ví dụ, chúng ta sử dụng hàm components(_:fromDate:) của lớp NSCalendar để tạo NSDateComponents từ NSDate.
- 4: In các thành phần của NSDateComponents ra log
Output:
day = 22, month = 11, year = 2015, week of year = 48, hour = 19, minute = 14, second = 43, nanosecond = 105728536
Trong hàm components(_:fromDate:) của lớp NSCalendar, chúng ta truyền vào 2 tham số, tham số thứ nhất là một mảng các phần tử của NSCalendarUnit và tham số thứ 2 là một đối tượng của NSDate. Ở đây, NSCalendarUnit là 1 struct, các bạn có thể xem tất cả các thuộc tính của Struct NSCalendarUnit tại đây. Trong ví dụ ở trên, tôi đã dùng những thuộc tính cơ bản hay được sử dụng khi làm việc với NSDate:
- day
- month
- year
- weak of year
- hour
- minute
- second
- nanosecond
Chú ý: đối với các thuộc tính của NSCalendarUnit chúng ta không truyền vào cho hàm components(_:fromDate:), thì chúng ta không thể gọi thuốc tính đấy của lớp NSDateComponents.
ví dụ, trong ví dụ trên tôi không truyền thuộc tính NSCalendarUnit.TimeZone cho hàm components, vì thế nên đối tượng dateComponents được tạo ra sẽ không có dateComponents.timeZone dù giá trị của timeZone có tồn tại trong đối tượng currentDate
b. Tạo đối tượng NSDate từ NSDateComponents
Ngược lại với việc tạo NSDateComponents từ NSDate, khi muốn tạo NSDate từ NSDateComponents, chúng ta cần có đối tượng NSDateComponents. Sau đó, tương tự như trên, chúng ta sử dụng hàm dateFromComponents(_