2010-02-04 26 views
8

Gần đây tôi đã gặp phải một vấn đề lớn, vì tôi có một hệ thống trả tiền cho khách hàng hàng tuần.Đánh số tuần ISO-8601 so với số "Outlook" trong PHP

Như chúng ta đều biết, một năm có 52 tuần và có các tiêu chuẩn cho nó. Tôi đang sử dụng PHP aka ngày ('W') để có được số tuần từ một ngày, mà tính toán rằng theo tiêu chuẩn ISO-8601.

Dưới đây là một số tài liệu tham khảo:

Nhưng đây là vấn đề: Năm 2009 có 53 tuần. Có vẻ như qua lịch Gregorian trong vòng 400 năm, có 71 năm có 53 tuần. Đó là một điều tôi không biết, và có lẽ nhiều điều không tốt.

Theo Wikipedia:

2009-12-31 là 2009-W53-4 (ISO năm 2009 có 53 tuần, kéo dài theo năm dương lịch 2009, mà bắt đầu và kết thúc với Thứ năm, ở cả hai đầu với ba ngày).

và chức năng ngày trong PHP hoàn toàn tôn trọng nó.

Nếu bạn nhìn vào MS Outlook và hiển thị ngày trong tuần ở chế độ xem lịch, nó sẽ xuất hiện 52 tuần xem xét 28/12/2009 đến 03 JAN 2010 tuần 1. Đây có phải là tiêu chuẩn khác không? Tiêu chuẩn của Mỹ hay gì đó?

Nếu có thì tại sao PHP không thể hỗ trợ? Có ai làm một chức năng hỗ trợ điều này không?

Có đúng 53 tuần không? Chúng tôi có cả khách hàng châu Âu và Mỹ.

+0

Câu hỏi thú vị. Tôi nhận thấy rằng Outlook có một tuần 53 vào năm 2011. Có vẻ như nó đang xác định "tuần 1" là tuần đầu tiên có chứa ngày 1 tháng 1. Vì tuần có thể bắt đầu vào Chủ Nhật hoặc Thứ Hai dựa trên cài đặt, nó thực sự có thể khác nhau người dùng. –

+0

Tôi vừa thử nó. Outlook sẽ cho phép bạn chọn bất kỳ ngày nào là ngày bắt đầu tuần, và đánh số tuần chỉ bắt đầu với tuần có chứa Jan 1. Do đó có bảy lược đồ đánh số khác nhau có sẵn trong Outlook. –

Trả lời

4

Tôi không nghĩ rằng bạn sẽ gặp sự cố ở đây. Sự thật là bạn đang tuân theo một tiêu chuẩn quốc tế về định dạng và tính ngày giờ (ISO8601). Nếu bạn có bất kỳ khách hàng nào phàn nàn, chỉ cần giới thiệu họ đến tiêu chuẩn.

đánh số tuần của Outlook là hơi tương đương như sau:

$dummyWeek = floor((date('z') + (date('N') - 1))/7) + 1; 

Đối với mục đích thanh toán, bạn nên sử dụng ISO8601 như một tiêu chuẩn. Trong thực tế, nếu bạn nhìn vào thuế của bạn mà bạn sẽ điền vào trong năm nay, họ sẽ mô tả năm tài chính cuối cùng là 53 tuần dài.

Vấn đề với cách đếm của Outlook là một tuần không được đảm bảo là 7 ngày. Ví dụ: OW01-2010 bị xâm phạm chỉ trong 2 ngày: Thứ Sáu ngày 1 tháng 1, ngày 7 tháng 1. Đó là khoảng thời gian thanh toán rất ngắn trong một tuần.

ISO8601 tuần được đảm bảo dài 7 ngày, đó là lý do tại sao chúng tôi cần một tuần nhuận mỗi 4/5/6 năm.

Mà một trong những tùy chọn bạn muốn:

  • ISO8601: Có 53 tuần một lần trong một thời gian, nhưng mỗi đơn một trong số họ là dài 7 ngày.
  • Outlook: Có 52/53 tuần trong một năm một cách ngẫu nhiên, nhưng phải trả hai lần một năm cho "nửa tuần".
+0

ngày 'z' và 'N'? – nathanchere

5

Outlook không tuân theo bất kỳ loại tiêu chuẩn nào cho đánh số tuần. Nó có hai cài đặt xác định đánh số tuần, được gọi là "Ngày đầu tiên trong tuần" và "Tuần đầu tiên của năm".

Bằng cách đặt "Ngày đầu tuần" thành Thứ Hai và "Tuần đầu tiên của năm" thành "Tuần đầu tiên 4 ngày", bạn có thể mô phỏng tiêu chuẩn ISO.

Mỗi người dùng sẽ phải thực hiện điều chỉnh này tuân theo tiêu chuẩn ISO.

Tôi biết không có tiêu chuẩn riêng biệt của Hoa Kỳ, và, rõ ràng, không phải Outlook.

0

Có nhiều thế giới bên ngoài nước Mỹ hơn là bên trong - và ISO 8601 có thể được sử dụng rộng rãi hơn bên ngoài nước Mỹ hơn là bên trong.

Câu lệnh đầu tiên 'một năm có 52 tuần' chỉ là một phần đúng, như bạn đã tìm thấy. Về tuần ISO, bạn có thể kết thúc với tuần 53, như đã nêu trong Wikipedia. Bạn có thể có tối đa ba ngày của Năm N + 1 trong tuần 52 của Năm N, hoặc tuần 53 của Năm N. Bạn cũng có thể có tối đa ba ngày của Năm N-1 trong Tuần 1 của Năm N. Và bạn cần phải xác định cả ISO 'tuần-năm' cũng như 'tuần' - bởi vì khi năm dương lịch là năm N, tuần theo năm của ISO có thể là năm N-1 hoặc N + 1 (tùy thuộc vào điểm cuối của năm bạn đang làm việc với). Đó là lý do tại sao có các định dạng riêng biệt ('% Y', '% y', '% g', '% G') trong ví dụ strftime() (nhưng lưu ý rằng tiêu chuẩn POSIX nghĩ rằng ngày trước Thứ Hai đầu tiên của tháng 1 là trong tuần 0 của năm hiện tại, không phải trong tuần 52 hoặc 53 của năm trước).

Dường như không có bất kỳ 'tiêu chuẩn Hoa Kỳ' đáng tin cậy nào cho 'tuần'. Bạn nhận được các kết quả khác nhau tùy thuộc vào phần mềm bạn sử dụng. Nếu bạn xem định nghĩa Oracle trong tuần, thì bảy ngày đầu tiên của năm là tuần thứ 1; bạn có 1 hoặc 2 ngày trong tuần 53 vào cuối năm.

Xem thêm SO 274861 để triển khai mã số tuần theo ISO. Ngay cả khi bạn không viết mã bằng ngôn ngữ, thuật toán phải dễ hiểu.

0

Chỉ một lời cảnh báo, nếu bạn đang sử dụng PHP, bạn cũng có thể đang sử dụng MySQL. MySQL không NOT tuân theo quy ước tuần ISO-8601 nhưng có đủ gần để bạn có thể nghĩ điều đó không. Như những người khác đang lưu ý về Outlook, cố gắng bắt chước một cách phi tiêu chuẩn để tính số tuần không phải là giá trị nó!

2

Đây là cách tôi đã giải quyết. Lưu ý: Tôi viết mã bằng PHP, nhưng thuật toán được thực hiện trong SQL là phần liên quan của mã của tôi bên dưới. Cũng lưu ý rằng tôi đã xử lý riêng '2028-12-31' bởi vì đó là ngày đặc biệt cung cấp 54 ngày làm số tuần.

// generate an sql that calculates the outlook week of $date (until 2033) 
function sqlWeek ($date) { 
    $week = "if(". $date . " = '2028-12-31', 54, (week(" . $date . ", 0) + if((year(" . $date . ") - 1) in (2011, 2016, 2022, 2033), 0, 1)) MOD (if (year(". $date .") = 2028, 54, if((year(".$date.") - 1) in (2011, 2016, 2022, 2033), 53, 52))))"; 

    return "concat(if(char_length(".$week.") < 2, concat('0', ".$week."), ".$week."), '/', year($date))"; 
} 
+0

Ngoài ra, xin lưu ý rằng tôi đã sử dụng "Tuần ('2011-11-09', 0)" có nghĩa là tuần bắt đầu vào Chủ nhật. Nếu nó bắt đầu vào thứ hai, bạn nên sử dụng "Tuần ('2011-11-09', 1)". – Amit

Các vấn đề liên quan