Нумерация недель ISO-8601 по сравнению с нумерацией "Outlook" в PHP


Недавно я столкнулся с большой проблемой, так как у меня есть система, которая платит клиентам еженедельно.

Как мы все знаем, в году 52 недели, и для этого существуют стандарты. Я использую PHP, он же дата ('W'), чтобы получить номер недели из даты, которая вычисляет это в соответствии со стандартом ISO-8601.

Вот некоторые ссылки:

Но вот в чем ПРОБЛЕМА: в 2009 году 53 недели. Похоже, что по григорианскому календарю в течение 400 лет насчитывается 71 год, в котором 53 недели. Это единственное, чего я не знал, и, вероятно, многие тоже не знали.

Согласно Википедии:

2009-12-31 - это 2009-W53-4 (2009 год по стандарту ISO имеет 53 недели, продлевая григорианский 2009 год, который начинается и заканчивается четвергом, с обоих концов с три дня).

И функция даты в PHP полностью ее уважает.

Если вы заглянете в MS Outlook и покажете день недели в представлении календаря, он будет отображаться 52 недели с 28 декабря 2009 года по 03 января 2010 года неделя 1. Это еще один стандарт? Американский стандарт или что-то в этом роде?

Если да, то почему PHP не может его поддерживать? Кто-нибудь создал функцию, которая поддерживала это?

Правильно ли иметь 53 недели? У нас есть как европейские, так и американские клиенты.

Author: Joe Doyle, 2010-02-04

5 answers

Я не думаю, что у вас здесь возникнут проблемы. Факт в том, что вы следуете международному стандарту форматирования и подсчета даты и времени (ISO8601). Если у вас есть клиенты, которые жалуются, просто обратитесь к стандарту.

Нумерация недель в Outlook несколько эквивалентна следующему:

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

Для выставления счетов вам лучше использовать ISO8601 в качестве стандарта. На самом деле, если вы посмотрите на свои налоги, которые вы собираетесь заполнить в этом году, они будут опишите последний финансовый год как 53 недели.

Проблема с перспективным способом подсчета заключается в том, что неделя не гарантированно составляет 7 дней. Например, OW01-2010 скомпрометирован всего на 2 дня: Пт 1 января, Сб 2 января. Это ужасно короткий расчетный период в течение недели.

ISO8601 недели гарантированно длятся 7 дней, поэтому нам нужна високосная неделя каждые 4/5/6 лет.

Какой из этих вариантов вы бы предпочли:

  • ISO8601: Имея 53 недели один раз в некоторое время, но каждый из них длится 7 дней.
  • Outlook: Имея 52/53 недели в году наугад, но вынужденный платить два раза в год за "половину недели".
 4
Author: Andrew Moore, 2010-02-04 18:49:10

Outlook не соответствует никаким стандартам нумерации недель. Он имеет две настройки, определяющие нумерацию недель, называемые "Первый день недели" и "Первая неделя года".

Установив "Первый день недели" на понедельник и "Первую неделю года" на "Первую 4-дневную неделю", можно смоделировать стандарт ISO.

Каждый пользователь должен будет внести эту корректировку, чтобы соответствовать стандарту ISO.

Я не знаю отдельного стандарта США, и, по-видимому, Outlook тоже не знает.

 5
Author: Jeffrey L Whitledge, 2010-02-04 18:23:23

Вот как я решил эту проблему. Примечание: Я пишу код на PHP, но алгоритм, реализованный в SQL, является соответствующей частью моего кода ниже. Также обратите внимание, что я обработал "2028-12-31" отдельно, потому что это особая дата, которая дает 54 в качестве номера недели.

// 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) )";
} 
 2
Author: Amit, 2011-11-09 13:45:43

За пределами США существует больше мира, чем внутри, и ISO 8601, вероятно, используется более широко за пределами США, чем внутри.

Первоначальное утверждение "в году 52 недели" верно лишь частично, как вы теперь обнаружили. Что касается недель ISO, вы можете закончить 53-ю неделю, как отмечено в Википедии. У вас может быть до трех дней в году N+1 на 52-й неделе года N или 53-й неделе года N. У вас также может быть до трех дней в году N-1 в неделю 1 года N. И вам необходимо определить как ISO "недельный год", так и "неделю", потому что, когда григорианский календарный год равен N, ISO-недельный год может быть годом N-1 или N+1 (в зависимости от того, с каким концом года вы работаете). Вот почему существуют отдельные спецификаторы формата ("%Y", "%y", "%g", "%G") в strftime(), например (но обратите внимание, что стандарт POSIX считает, что дни до первого понедельника января относятся к 0-й неделе текущего года, а не к 52 или 53-й неделе предыдущего год).

Похоже, что для "недели" не существует какого-либо надежного "стандарта США". Вы получаете разные результаты в зависимости от используемого вами программного обеспечения. Если вы посмотрите на определение недели Оракула, то первые семь дней в году - это неделя 1; у вас есть 1 или 2 дня на 53-й неделе в конце года.

Смотрите также SO 274861 для реализации кода номеров недель ISO. Даже если вы не кодируете на этом языке, алгоритм должен быть легко понятен.

 0
Author: Jonathan Leffler, 2017-05-23 10:27:34

Просто слово предупреждения, если вы используете PHP, вы также можете использовать MySQL. MySQL не НЕ следует соглашениям недели ISO-8601, но достаточно близко, чтобы вы могли подумать, что это так. Как отмечают другие люди о Outlook, пытаться имитировать шаткий нестандартный способ вычисления чисел недель не стоит!

 0
Author: pr1001, 2010-02-04 19:05:52