2010-02-04 23 views
8

Recientemente me encontré con un gran problema, ya que tengo un sistema que les paga semanalmente a los clientes.Numeración de la semana ISO-8601 frente a la numeración de "Outlook" en PHP

Como todos sabemos, un año tiene 52 semanas, y hay estándares para ello. Estoy usando PHP aka date ('W') para obtener el número de semana de una fecha, que calcula eso de acuerdo con el estándar ISO-8601.

Aquí están algunas referencias:

Pero aquí está el problema: el año 2009 tiene 53 semanas. Parece que a través del calendario gregoriano dentro de 400 años hay 71 años que tienen 53 semanas. Eso es algo que no sabía, y probablemente muchos no lo hicieron.

Según Wikipedia:

2009-12-31 es 2009-W53-4 (ISO año 2009 tiene 53 semanas, que se extienden al año gregoriano de 2009, que comienza y termina con el jueves en ambos extremos con tres días).

y la función de fecha en PHP lo respeta totalmente.

Si mira en MS Outlook y muestra el día de la semana en la vista del calendario, aparecerá 52 semanas considerando el 28 DIC 2009 al 03 ENE 2010 semana 1. ¿Es este otro estándar? El estándar de los Estados Unidos o algo así?

Si es así, ¿por qué PHP no puede soportarlo? ¿Alguien hizo una función que apoyó esto?

¿Es correcto tener 53 semanas? Tenemos clientes europeos y estadounidenses.

+0

Interesante pregunta. Noté que Outlook tiene una semana 53 en 2011. Parece que está definiendo "semana 1" como la primera semana que contiene el 1 de enero. Dado que las semanas pueden comenzar el domingo o el lunes según una configuración, en realidad podría ser diferente para diferentes usuarios. –

+0

Acabo de intentarlo. Outlook le permitirá elegir cualquier día para ser el día de inicio de la semana, y la numeración de la semana simplemente comienza con la semana que contiene el 1 de enero. Por lo tanto, hay siete esquemas de numeración diferentes disponibles en Outlook. –

Respuesta

4

No creo que tenga un problema aquí. El hecho es que está siguiendo un estándar internacional para el formato y conteo de fecha y hora (ISO8601). Si tiene clientes que se quejan, simplemente refiéralos al estándar.

numeración semanas de Outlook es un tanto equivalente a lo siguiente:

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

Para fines de facturación, que es mejor usar ISO8601 como un estándar. De hecho, si observa sus impuestos que va a completar este año, describirán el último año fiscal como de 53 semanas.

El problema con la manera de contar de Outlook es que no se garantiza que una semana sea de 7 días. Por ejemplo, OW01-2010 está comprometido de solo 2 días: viernes 1 de enero y sábado 2 de enero. Ese es un período de facturación terriblemente corto para una semana.

ISO8601 Se garantiza que las semanas son de 7 días, por lo que necesitamos un salto semanal cada 4/5/6 años.

¿Cuál de estas opciones preferiría usted:

  • ISO8601: tener 53 semanas de vez en cuando, pero cada uno de ellos es de 7 días de duración.
  • Outlook: tener 52/53 semanas en un año al azar, pero tener que pagar dos veces al año durante una "media semana".
+0

fecha 'z' y 'N'? – nathanchere

5

Outlook no sigue ningún tipo de estándar para la numeración semanal. Tiene dos configuraciones que determinan la numeración de la semana, llamada "Primer día de la semana" y "Primera semana del año".

Al establecer "Primer día de la semana" al lunes y "Primera semana del año" a "Primera semana de cuatro días", se puede simular el estándar ISO.

Cada usuario tendrá que hacer este ajuste para seguir el estándar ISO.

No conozco un estándar separado de EE. UU., Y, al parecer, tampoco lo hace Outlook.

0

Hay más mundo afuera de los EE. UU. Que dentro, y ISO 8601 probablemente se usa más fuera de EE. UU. Que dentro.

La afirmación inicial 'un año tiene 52 semanas' es parcialmente cierta, como ya lo ha descubierto. En términos de semanas ISO, puede terminar con la semana 53, como se indica en Wikipedia. Puede tener hasta tres días de Año N + 1 en la semana 52 del año N, o la semana 53 del año N. También puede tener hasta tres días del año N-1 en la semana 1 del año N. Y debe determinar tanto ISO 'semana-año' como 'semana', porque cuando el año calendario gregoriano es N, el año-semana ISO puede ser año N-1 o N + 1 (dependiendo de qué final del año año con el que está trabajando). Es por eso que hay especificadores de formato separados ('% Y', '% y', '% g', '% G') en strftime(), por ejemplo (pero tenga en cuenta que el estándar POSIX cree que días antes del primer lunes de enero en la semana 0 del año actual, no en la semana 52 o 53 del año anterior).

No parece haber ningún 'estándar estadounidense' confiable para 'semana'. Obtienes diferentes resultados dependiendo del software que usas. Si nos fijamos en la definición de semana de Oracle, los primeros siete días del año son la semana 1; tiene 1 o 2 días en la semana 53 al final del año.

Consulte también SO 274861 para una implementación del código de números de semana ISO. Incluso si no codifica en el idioma, el algoritmo debería ser fácilmente comprensible.

0

Solo una palabra de advertencia, si está utilizando PHP también podría estar utilizando MySQL. MySQL hace NOT sigue las convenciones de la semana ISO-8601 pero se acerca lo suficiente como para que creas que sí. Como otras personas están notando acerca de Outlook, tratar de imitar una forma poco convencional de calcular números semanales no vale la pena.

2

Aquí está la manera en que lo resolví. Nota: código en PHP, pero el algoritmo implementado en SQL es la parte relevante de mi código a continuación. También tenga en cuenta que manejé '2028-12-31' por separado porque es una fecha especial que da 54 ya que es el número de la semana.

// 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

Además, tenga en cuenta que utilicé "Semana ('2011-11-09', 0)", lo que significa que la semana comienza el domingo. Si comienza el lunes, debe usar "Semana ('2011-11-09', 1)". – Amit

Cuestiones relacionadas