Conserva un valor de fecha de publicación sin hora analizándolo como fecha de calendario y manteniendo esa fecha como referencia autoritativa. Si una exportación requiere una marca de tiempo UTC, añade explícitamente la convención de medianoche UTC. Este recorrido por Terminal en Mac muestra la diferencia y comprueba la conversión de ida y vuelta.
Determina qué significa realmente el campo de publicación
Supongamos que una lista de publicaciones contiene el valor sintético 2028-06-15. Tu tarea es validar ese valor y prepararlo para una exportación sin mostrar accidentalmente el 14 de junio. Antes de elegir un analizador, decide si el campo registra el día de publicación o el momento exacto de la publicación.
Estos cuatro conceptos tienen funciones distintas:
| Concepto | Ejemplo sintético | Significado |
|---|---|---|
| Fecha civil | 2028-06-15 |
Un día del calendario, sin hora ni desplazamiento |
| Instante | 2028-06-15T00:00:00+00:00 |
Un momento específico expresado en UTC |
| Desplazamiento UTC | +09:00 |
La diferencia entre la hora local del reloj y UTC |
| Zona con nombre | America/Los_Angeles |
Un identificador que se usa para obtener las reglas aplicables de zona horaria |
RFC 3339 define por separado una full-date y una date-time; su gramática de marcas de tiempo añade una hora y un desplazamiento a la fecha. Por tanto, una fecha de publicación sin más información no contiene lo necesario para identificar un instante de publicación. Elegir la medianoche añade información que no estaba en la entrada. RFC 3339, sección 5.6
Una zona con nombre también contiene más información que un solo desplazamiento numérico. La documentación de Python sobre zoneinfo muestra cómo una zona puede tener distintos desplazamientos durante un cambio al horario de verano. Para una etiqueta de fecha sin hora, no es necesario resolver esas reglas. Python: compatibilidad con zonas horarias IANA
Antes de exportar, aplica esta regla de decisión:
- El campo significa «publicado este día»: conserva un valor sin hora durante el almacenamiento y la visualización.
- El formato de destino requiere una marca de tiempo: conserva la fecha y genera un valor portador de medianoche UTC conforme a una convención documentada.
- El campo significa «publicado en este momento»: obtén la hora y el desplazamiento reales, o la hora y la zona con nombre necesarias para determinar ese momento.
La convención del valor portador es útil para mantener la compatibilidad, pero no permite recuperar una hora de publicación desconocida. Un nombre de campo como utc_carrier deja clara esa limitación; llamarlo published_at sugeriría que se conoce información que la fuente nunca proporcionó.
Entiende dónde se produce el error del día anterior
Considera dos posibles rutas de procesamiento para 2028-06-15. En la primera, un programa inventa la medianoche con el desplazamiento fijo +09:00 y luego convierte ese instante a UTC. El resultado es 2028-06-14T15:00:00+00:00: restar nueve horas cruza el límite del día.
En la segunda ruta, el programa crea deliberadamente la medianoche UTC: 2028-06-15T00:00:00+00:00. Al representar ese mismo instante con el desplazamiento fijo -07:00, se obtiene 2028-06-14T17:00:00-07:00. Son cálculos ilustrativos de desplazamientos, no afirmaciones sobre el desplazamiento de una zona con nombre en esa fecha.
Ambos cálculos conservan sus respectivos instantes. Ninguno conserva la etiqueta original del calendario en todas las zonas de representación. Python documenta que astimezone() ajusta los campos del reloj mientras conserva la hora UTC representada. Python: datetime.astimezone()
La consecuencia práctica es que el análisis y la representación necesitan un contrato común. Si una fecha se ha colocado en un valor portador de medianoche UTC, recupera sus campos de calendario en UTC. Si quieres que la etiqueta de publicación no cambie cuando alguien abra la exportación, muestra la fecha civil conservada.
No des por sentado que todos los lenguajes proporcionan la misma información que falta. ECMAScript especifica que las formas de fecha sin desplazamiento se interpretan como UTC, mientras que las formas de fecha y hora sin desplazamiento se interpretan como hora local. Por tanto, añadir T00:00:00 a una cadena puede cambiar su interpretación en JavaScript. ECMAScript: Date.parse
Ejecuta una comprobación completa de fechas de publicación en Terminal para Mac
Este recorrido valida tres fechas sintéticas, imprime una vista previa delimitada por tabuladores y comprueba el rechazo de entradas mal formadas. No modifica una lista de publicaciones ni crea un archivo de exportación.
En Finder, abre /Applications/Utilities y haz doble clic en Terminal. Apple documenta que esta es una forma admitida de abrir la aplicación de línea de comandos. Apple: abrir o salir de Terminal en Mac
Ejecuta el siguiente comando para comprobar tu intérprete:
python3 --version
Para este recorrido, usa Python 3.11 o posterior. Si python3 no está disponible o indica una versión anterior, sigue las instrucciones oficiales de instalación para macOS antes de continuar; luego vuelve a abrir Terminal y compruébalo de nuevo. Python documenta tanto su instalador para macOS como la ejecución de scripts con python3. Python: uso de Python en macOS
Pega el bloque completo de abajo, incluido el PY final, y pulsa Return. El argumento - indica a Python que lea el programa desde la entrada estándar. Se incluyen todos los datos de ejemplo y las importaciones. Python: línea de comandos y entorno
python3 - <<'PY'
import re
from datetime import date, datetime, time, timezone
def parse_publication_date(text):
if not isinstance(text, str) or re.fullmatch(
r"[0-9]{4}-[0-9]{2}-[0-9]{2}", text
) is None:
raise ValueError("Expected YYYY-MM-DD")
return date.fromisoformat(text)
def utc_carrier(day):
return datetime.combine(day, time(0), tzinfo=timezone.utc)
samples = ["2028-02-29", "2028-06-15", "2028-12-31"]
parsed = [(text, parse_publication_date(text)) for text in samples]
print("publication_date\tutc_carrier")
for original, day in parsed:
carrier = utc_carrier(day)
assert day.isoformat() == original
assert carrier.astimezone(timezone.utc).date() == day
print(day.isoformat(), carrier.isoformat(timespec="seconds"), sep="\t")
for invalid in [
"2027-02-29",
"2028-6-15",
"2028-06-15T00:00:00",
" 2028-06-15",
]:
try:
parse_publication_date(invalid)
except ValueError:
pass
else:
raise AssertionError(f"Unexpected acceptance: {invalid!r}")
print("Round-trip and rejection checks passed.")
PY
El resultado esperado es:
publication_date\tutc_carrier
2028-02-29\t2028-02-29T00:00:00+00:00
2028-06-15\t2028-06-15T00:00:00+00:00
2028-12-31\t2028-12-31T00:00:00+00:00
Round-trip and rejection checks passed.
El ejemplo y los dos cálculos con desplazamientos fijos se ejecutaron correctamente con el intérprete de Python disponible. Las instrucciones específicas para Mac, sobre cómo abrir la aplicación y el intérprete, se basan en la documentación oficial enlazada.
Por qué el ejemplo conserva el día de publicación
El analizador comprueba por separado dos aspectos: la forma exacta de la cadena y la validez de la fecha del calendario. Su expresión regular exige cuatro dígitos para el año, dos para el mes y dos para el día. A continuación, el analizador de fechas rechaza las fechas imposibles. Así se evita que una columna de publicaciones acepte silenciosamente marcas de tiempo, espacios alrededor del valor o formatos abreviados.
Esa comprobación explícita de la forma es importante porque date.fromisoformat() también acepta otras representaciones ISO, incluidas las fechas compactas y las fechas semanales. datetime.combine() añade entonces, de forma deliberada, la medianoche y UTC. Python: tipos básicos de fecha y hora
El programa analiza toda la lista de ejemplo antes de imprimir el encabezado. Si sustituyes un ejemplo por un valor no válido, la ejecución se detiene antes de que aparezca ninguna fila de vista previa. Las comprobaciones de entradas no válidas del final son pruebas independientes; se capturan las excepciones esperadas para poder comprobar todos los casos de rechazo.
Dos aserciones de conversión de ida y vuelta expresan el contrato. La primera verifica que el análisis y el formato de fecha reproducen la etiqueta original. La segunda verifica que el valor portador derivado devuelve la misma fecha al interpretarlo en UTC. En conjunto, comprueban la tarea exacta de conservar la fecha, en lugar de limitarse a comprobar si se puede producir alguna marca de tiempo.
El resultado usa explícitamente +00:00. RFC 3339 también permite Z como designador del desplazamiento UTC, pero añadir cualquiera de los dos sufijos a una fecha sin más información no proporciona el componente de hora que falta. Conserva el formato de fecha sin hora o construye la marca de tiempo completa de forma intencional. RFC 3339, sección 5.6
Diagnostica una exportación que sigue cambiando la fecha
Si una vista previa posterior muestra el día anterior, inspecciona los valores en cada límite. Usa la muestra sintética del medio, 2028-06-15, para poder comparar cada etapa con una etiqueta conocida.
| Punto de control | Resultado esperado con la convención del valor portador | Qué sugiere una diferencia |
|---|---|---|
| Campo de publicación original | 2028-06-15 |
La entrada cambió antes del análisis |
| Fecha analizada y representada como texto | 2028-06-15 |
El análisis o la normalización cambió la etiqueta |
| Valor portador UTC derivado | 2028-06-15T00:00:00+00:00 |
Se introdujo otra hora o desplazamiento |
| Fecha recuperada en UTC | 2028-06-15 |
La conversión o extracción usó un contrato incorrecto |
| Etiqueta de publicación mostrada al lector | 2028-06-15 |
El visor puede estar mostrando el valor portador en otra zona |
Comprueba el sistema de representación independientemente del analizador. Un valor portador UTC correcto puede seguir produciendo un día distinto si se muestra con la configuración de una zona local. Para una etiqueta de publicación, proporciona al sistema de representación la fecha sin hora conservada. Si solo acepta marcas de tiempo, usa una opción de visualización en UTC documentada y verifica el resultado.
Si la herramienta de destino solo admite instantes y siempre los representa en la hora local, la convención de medianoche UTC no puede garantizar que la etiqueta de fecha permanezca igual. Conserva una columna de texto separada con la fecha sin hora, usa un campo de fecha sin hora admitido o elige un sistema de representación con formato UTC explícito. La limitación se deriva de los cálculos de desplazamiento anteriores; cambiar solo el analizador no puede eliminarla.
Evita también tratar una marca de tiempo existente como si fuera una fecha de entrada sin hora. Para un instante real, cambiar su zona significa convertirlo. Python distingue esa operación de reemplazar tzinfo, que adjunta información de zona sin ajustar los campos del reloj. Python: comportamiento de la conversión de zona horaria
Para tu lista de publicaciones, conserva publication_date como el valor de calendario de referencia. Deriva un valor portador UTC solo en una interfaz que lo requiera, acompaña el campo con la convención y verifica la extracción UTC antes de confiar en la vista previa. Así tendrás una forma repetible de conservar el día proporcionado sin inventar un momento de publicación.
Fuentes
- Abrir o salir de Terminal en Mac — Apple.
- Uso de Python en macOS — Python Software Foundation.
- Línea de comandos y entorno — Python Software Foundation.
- datetime — Tipos básicos de fecha y hora — Python Software Foundation.
- zoneinfo — Compatibilidad con zonas horarias IANA — Python Software Foundation.
- RFC 3339: Fecha y hora en Internet: marcas de tiempo — RFC Editor.
- Especificación del lenguaje ECMAScript: números y fechas — Ecma International / TC39.