+6

Problem của việc set date là 31-12-2017

Vấn đề này đã từng được nêu từ năm 2014, tuy nhiên thời gian gần đây mình lại được nghe lại lỗi này. Và năm nay cũng tròn năm có thể mắc lỗi đó, nên trong bài viết này mình xin được chia sẻ với các bạn lỗi set date đó. Lỗi đó chính là Nếu ta dùng hàm dateFormat của DateFormaterYYYY-MM-dd để set date thì khi ta truyền vào 2017-12-31 , kết quả sẽ trả lại giá trị đó là 2018-12-31 Vấn đề này không liên quan đến Swift mà đó là Spec của ISO. Cũng do lỗi này mà app Twitter của Android đã bị down mất hơn 5 tiếng không sử dụng được vào ngày 29-12-2014 do server tưởng là năm 2015.

let datecomponens = DateComponents(year: 2017, month: 12, day: 31)
let calendar = Calendar.current
let date = calendar.date(from: datecomponens)

let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX")
f.dateFormat = "YYYY-MM-dd"

f.string(from: date!) // "2018-12-31"

Chúng ta cũng có thể xem ví dụ tái hiện bug này ở bài viết ở Blog sau cũng mới được đề cập gần đây :

Lý do ở đây đó là YYYY là thể hiện cho "Tuần của năm" (Week of Year), ngày 31-12-2017 lại thuộc tuần của năm 2018 (tuần đầu tiên), nên kết quả hiển thị ra sẽ là 2018. Để hiển thị chính xác năm của ngày đó chúng ta cần sử dụng ký hiệu y thường yyyy.

Ở Document của Apple cũng có viết chú ý về vấn đề này

It uses yyyy to specify the year component. A common mistake is to use YYYY. 
yyyy specifies the calendar year whereas YYYY specifies the year (of “Week of Year”), used in the ISO year-week calendar. 
In most cases, yyyy and YYYY yield the same number, however they may be different. 
Typically you should use the calendar year.
  • Data Formatting Guide - Apple Developers Tức là trong đa số trường hợp, kết quả vẫn hiển thị ra chính xác, đó mới là điều làm cho chúng ta chủ quan. Ví dụ như nếu là năm 2016 thì hoàn toàn chính xác
let datecomponens = DateComponents(year: 2016, month: 12, day: 31)
let calendar = Calendar.current
let date = calendar.date(from: datecomponens)

let f = DateFormatter()
f.locale = Locale(identifier: "en_US_POSIX")
f.dateFormat = "YYYY-MM-dd"

f.string(from: date!) // "2016-12-31"

Nên năm ngoái thì ta ko cần phải chú ý gì cả. Vấn đề khác nhau giữa yyyyYYYY chi tiết hơn các bạn có thể tham khảo tại bài viết sau

Năm đã gần hết tết đã gần đến rồi. Chúc toàn thể a/c/e giáng sinh vui vẻ, năm mới hạnh phúc 😄 😄 😄 😄 😄


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí