Pregunta ¿Hay un estándar para los intervalos de final de tiempo inclusivos / exclusivos?


Me pregunto si hay un estándar o medios "normales" de interpretar puntos finales de datos de intervalo de tiempo con respecto a la inclusión / exclusividad del valor que define el punto final. Sin embargo, tenga en cuenta que estoy preguntando cuál es el estándar (o más común) convención es (si hay uno), no para una tesis sobre su preferencia personal. Si realmente desea proporcionar una disertación, adjúntela a una referencia a la norma publicada de alguien o un texto estándar sobre el tema. Los estándares abiertos (que no tengo que pagar para leer) son muy preferidos a menos que sean fundamentalmente defectuosos :).

Por supuesto, hay 4 posibilidades para un intervalo de tiempo de A a B:

  1. (A, B): ambos extremos son exclusivos.
  2. [A, B] - Ambos extremos son inclusivos.
  3. [A, B) - El inicio es inclusivo y el final es exclusivo
  4. (A, B] - El inicio es exclusivo y el final es inclusivo

Cada uno de estos tiene diferentes características (como yo lo veo, no dudes en señalarlo más)

La convención [A, B] tendría la propiedad aparentemente inconveniente de que B está contenida con el inteval [A, B] y también [B, C]. Esto es particularmente inconveniente si B pretende representar el límite de la medianoche y está tratando de determinar por qué día cae, por ejemplo. Además, esto significa que la duración del intervalo es ligeramente irritante para calcular ya que [A, B] donde A = B debe tener una longitud de 1 y, por lo tanto, la duración de [A, B] es (B - A) + 1 

De manera similar, la convención (A, B) tendría la dificultad de que B no está dentro de (A, B) ni (B, C) ... continuando la analogía con los límites del día, la medianoche no sería parte de ninguno de los días. Esto también es lógicamente inconveniente porque [A, B] donde A = B es un intervalo sin sentido con una duración inferior a cero, pero invertir A y B no lo convierte en un intervalo válido.

Así que creo que quiero [A, B) o (A, B] y no sé cómo decidir entre ellos.

Entonces, si alguien tiene un enlace a un documento de estándares, la referencia a un texto estándar o similar que aclare la convención sería grandioso. Alternativamente, si puede vincular una variedad de documentos estándar y / o referencias que más o menos completamente no llegan a un acuerdo, entonces puedo elegir uno que parezca tener suficiente autoridad para CMA y terminarlo :).

Finalmente, estaré trabajando en Java, por lo que soy particularmente susceptible a las respuestas que funcionan bien en Java.


32
2018-03-20 21:38


origen


Respuestas:


En el caso general, [A, B) tiene mucho que ofrecer y no veo ninguna razón por la cual no sea cierto para los intervalos de tiempo.

Djikstra escribió un buen artículo al respecto Por qué la numeración debería comenzar en cero que, a pesar del nombre, trata principalmente de esto exactamente.

Breve resumen de las ventajas:

  • end - start es igual a la cantidad de elementos en la lista
  • el límite superior del intervalo precedente es el límite inferior del siguiente
  • permite indexar un intervalo comenzando desde 0 con números sin signo [1]

Personalmente, el segundo punto es extremadamente útil para muchos problemas; considere una función recursiva bastante estándar (en pseudo python):

def foo(start, end):
    if end - start == 1:
        # base case
    else:
        middle = start + (end - start) / 2
        foo(start, middle)
        foo(middle, end)

Escribir lo mismo con un límite superior inclusivo introduce una gran cantidad de error propenso a un error.

[1] Esa es la ventaja en comparación con (A, B] - un intervalo que comienza desde 0 es MUCHO más común que un intervalo que termina en MAX_VAL. Tenga en cuenta que también se relaciona con un problema adicional: el uso de dos límites inclusivos significa que podemos denotar una secuencia cuya longitud no se puede expresar con el mismo tamaño.


37
2018-03-21 18:09



Proporcionaré lo que escribí para nuestro equipo como respuesta usando el enlace de Voo hasta que Voo agregue una respuesta, luego le daré crédito. Esto es lo que decidí por nuestro caso:

Los intervalos de tiempo en nuestras aplicaciones se representarán como un par de   tiempos instantáneos con la convención de que la hora de inicio es   inclusive y el tiempo de finalización es exclusivo. Esta convención es   matemáticamente conveniente en que la diferencia de los límites es   igual a la duración del intervalo, y también es numéricamente   consistente con la forma en que las matrices y las listas están suscritas en java   programas (ver http://www.cs.utexas.edu/~EWD/ewd08xx/EWD831.PDF) los   resultado práctico de esto es ese intervalo 2012-03-17T00: 00: 00.000Z -   2012-03-18T00: 00: 00.000Z denota la totalidad del Día de San Patricio,   y cada fecha que comience con 2012-03-17 se identificará como   incluido en el Día de San Patricio, pero 2012-03-18T00: 00: 00.000Z no será   incluido, y el día de San Patricio incluirá exactamente 24 * 60 * 60 * 1000   milisegundos.


4
2018-03-21 14:59



No puedo decirlo con certeza, pero dudo que exista una norma o convención. Si incluye o no el inicio o el final dependerá de su caso de uso, así que considere si son importantes para usted. Si la decisión es arbitraria, elija una, tenga en cuenta que la elección es arbitraria y continúe.

En cuanto a lo que se admite en Java, la biblioteca Joda Time implementa Intervals que incluyen la hora de inicio pero no la hora de finalización


2
2018-03-20 21:45



A pesar de que este hilo se centra más en Java, pensé que sería bastante interesante ver otras convenciones adoptadas, especialmente dado que el pandas Pitón biblioteca es omnipresente para el análisis de datos en estos días, y el hecho de que esta página de StackOverflow es uno de los principales resultados de búsqueda al buscar convenciones sobre la inclusión / exclusividad de los intervalos de tiempo.

Citando esta página:

Las fechas de inicio y final son estrictamente inclusivas. Por lo tanto, si no se especifica, no generará ninguna fecha fuera de esas fechas.

Además, no solo genera intervalos de fechas. La convención también se adopta cuando se trata de indexar en series temporales de datos. Aquí hay una prueba simple en marcos de datos con DatetimeIndex

>>> import pandas as pd
>>> pd.__version__
'0.20.2'
>>> df = pd.DataFrame(list(range(20)))
>>> df.index = pd.date_range(start="2017-07-01", periods=20)
>>> df["2017-07-01":"2017-07-05"]
            0
2017-07-01  0
2017-07-02  1
2017-07-03  2
2017-07-04  3
2017-07-05  4

1
2017-08-02 19:23



java.time y Half-Open

los java.time las clases que suplantan las problemáticas clases de fecha y hora heredadas, así como el proyecto Joda-Time, definen un lapso de tiempo usando el enfoque de Medio Abierto [) donde el comienzo es inclusivo mientras que el final es exclusivo.

Para la fecha y hora con una fracción de segundo, esto elimina el problema de intentar capturar el último momento. El último segundo infinitamente divisible debe resolverse, pero varios sistemas usan varias granularidades, como milisegundos, microsegundos, nanosegundos u otra cosa. Con Half-Open, un día, por ejemplo, comienza en el primer momento del día y se extiende hasta, pero lo hace no incluir, el primer momento del día siguiente. Problema resuelto, no hay necesidad de luchar con el último momento del día y su fracción de segundo.

He llegado a ver los beneficios de usar este enfoque de manera consistente a lo largo de todo mi código de manejo de fecha y hora. Por ejemplo, una semana que comienza el lunes se extiende hasta el lunes siguiente, pero no incluye. Un mes comienza el día 1 y se extiende hasta el primer día del mes siguiente, pero no incluye, por lo tanto, ignora el desafío de determinar el número del último día del mes, incluido el 28 de febrero del año bisiesto.

Otro beneficio del uso consistente de Half-Open [) es la reducción de la carga cognitiva cada vez que tengo que detectar, descifrar y verificar un fragmento del enfoque de lapso de tiempo del código. En mi propia programación, simplemente busco una mención de Half-Open en un comentario en la parte superior y sé instantáneamente cómo leer ese código.

Un resultado del uso constante de Half-Open es la reducción de la posibilidad de errores en mi código, ya que mi estilo de pensamiento y de escritura es uniforme y no hay posibilidad de confundirme con el exclusivo inclusivo.

Por cierto, tenga en cuenta que Half-Open [) significa evitar el SQL BETWEEN conjunción ya que eso siempre está completamente cerrado [].

En cuanto al pensamiento comercial de los clientes a los que sirvo, cuando sea apropiado, trato de convencerlos de que también usen Half-Open constantemente. He visto muchas situaciones en las que varias personas de negocios estaban haciendo suposiciones incorrectas sobre los períodos de tiempo cubiertos en los informes. El uso constante de Half-Open evita estas desafortunadas ambigüedades. Pero si el cliente insiste, anoto esto en mi código y ajuste las entradas / salidas para usar Half-Open dentro de mi propia lógica. Por ejemplo, mi lógica utiliza una semana de lunes a lunes, pero en un informe resta un día para mostrar el domingo.

Para aún más clases que representan períodos de tiempo con el enfoque de Medio Abierto [), vea el ThreeTen-Extras proyecto para su Interval clase (un par de Instant objetos) y el LocalDateRange clase (un par de LocalDate objetos).


Acerca de java.time

los java.time framework está integrado en Java 8 y posterior. Estas clases suplantan a los viejos problemas legado clases de fecha y hora como java.util.Date, Calendar, Y SimpleDateFormat.

los Joda-Time proyecto, ahora en modo de mantenimiento, aconseja la migración a java.time clases

Para obtener más información, vea el Tutorial de Oracle. Y busque Stack Overflow para obtener muchos ejemplos y explicaciones. La especificación es JSR 310.

¿Dónde obtener las clases de java.time?

los ThreeTen-Extra proyecto extiende java.time con clases adicionales. Este proyecto es un terreno de prueba para posibles adiciones futuras a java.time. Puede encontrar algunas clases útiles aquí, como Interval, YearWeek, YearQuartery Más.


1
2017-08-02 23:29



Acabo de pasar por este mismo proceso de pensamiento y creo que es muy importante que esto esté estandarizado de alguna manera, o al menos aclarado mediante este tipo de publicaciones de preguntas y respuestas.

En nuestro caso, los intervalos de fechas en cuestión se utilizan como entradas y salidas hacia / desde un microservicio; uno que, a corto plazo al menos, será llamado por una aplicación monolítica existente (es un proyecto de descomposición monolítica). Por lo tanto, creo que el comentario anterior relacionado con la decisión impulsada por los requisitos del negocio es, en nuestro caso, menos relevante (porque el directo "usuarios" del software que estamos construyendo son personas realmente técnicas). ¡Si manejáramos la información de un selector de fechas, esa podría ser una historia diferente!

Mi recomendación es que todas las fechas de inicio sean inclusivas y que todas las fechas de finalización sean exclusivas, por lo que [A, B] en su notación. Esto fue por las siguientes razones:

  1. Acordamos previamente que cualquier fecha entrante que contuviera partes horarias sería rechazada (incluso si el valor JSON era "2018-01-01T00: 00: 00") y que obtendríamos todas las fechas sin tiempos. Por lo tanto, si la fecha de finalización es exclusiva, tan pronto como la cadena se deserialice en el objeto .NET DateTime, sería un día de inactividad.

  2. Me gusta la idea de que los intervalos de fechas (que en nuestro caso siempre deberían rendir días enteros) siempre se pueden calcular simplemente haciendo dateRange = (endDateExcl - startDateIncl) .TotalDays. ¡No es necesario agregar 1 en todas partes!

  3. Gran parte de la validación de negocios realizada por el servicio es verificar que múltiples rangos de datos estén alineados entre sí sin espacios vacíos. Esto es fácil de controlar cuando se usa [A, B] porque cada B debe coincidir con la A anterior. Si vamos con [A, B], entonces nosotros (desarrolladores, evaluadores, ingenieros de soporte) a menudo nos preguntaríamos "¿Cuántos días? está en marzo otra vez? " (por ejemplo [2018-03-01,2018-03-30], [2018-04-01,2018-04-30]) o "¿2016 tiene un día bisiesto?" (por ejemplo, [2016-02-01,2016-02-28], [2016-03-01,2016-03-30]).

Solo para agregar, recomiendo encarecidamente que cualquiera, independientemente de la decisión, sufija explícitamente todos los nombres de atributos, variables, métodos o de lo contrario con "Incl" o "Excl" para que quede claro para todos sin tener que buscar la documentación.

También recomendamos que todas las fechas aparezcan en formato ISO y que cualquier cosa con una "Z" al final también deba rechazarse (porque la comprensión es que estamos trabajando en días completos y no queremos una fecha para se deserializará en un objeto DateTime con una hora deshonesta (¡o 23!) debido al horario de verano).

Nota al pie, probablemente hubiera publicado esto como un comentario a la respuesta de Voo, pero acabo de (¡tardíamente!) Me uní a SO y necesito ganar mis felicitaciones antes de poder hacerlo. ;-)

Feliz cita x


1
2017-11-03 18:05