Tutoriales

Mejores Prácticas de Validación de Timestamps: Guía Completa

Introducción

La validación de timestamps es crucial para la seguridad y confiabilidad de tu aplicación. Este tutorial cubre las mejores prácticas para validar timestamps en diferentes contextos.

Lo que Aprenderás

  • ✅ Validación de formato y longitud
  • ✅ Validación de rango
  • ✅ Validación de precisión
  • ✅ Validación de zona horaria
  • ✅ Consideraciones de seguridad

Validación de Formato

JavaScript

function validarTimestamp(valor) {
  // Debe ser número o string numérico
  const num = Number(valor);

  if (isNaN(num)) {
    return { valido: false, error: 'No es un número válido' };
  }

  // Verificar longitud para determinar precisión
  const str = String(Math.floor(num));
  const longitudes = [10, 13, 16, 19];

  if (!longitudes.includes(str.length)) {
    return { 
      valido: false, 
      error: `Longitud inválida: ${str.length}. Esperado: ${longitudes.join(', ')}` 
    };
  }

  return { valido: true, precision: obtenerPrecision(str.length) };
}

function obtenerPrecision(longitud) {
  const mapa = { 10: 'segundos', 13: 'milisegundos', 16: 'microsegundos', 19: 'nanosegundos' };
  return mapa[longitud];
}

Python

def validar_timestamp(valor: str) -> dict:
    """Valida formato de timestamp"""
    # Solo dígitos
    if not valor.isdigit():
        return {'valido': False, 'error': 'Debe contener solo dígitos'}

    longitud = len(valor)
    precisiones = {10: 'segundos', 13: 'milisegundos', 16: 'microsegundos', 19: 'nanosegundos'}

    if longitud not in precisiones:
        return {
            'valido': False, 
            'error': f'Longitud inválida: {longitud}. Esperado: {list(precisiones.keys())}'
        }

    return {'valido': True, 'precision': precisiones[longitud]}

Validación de Rango

Rangos Válidos por Precisión

PrecisiónMínimoMáximoAño MinAño Max
Segundos (32-bit)0214748364719702038
Segundos (64-bit)025340230079919709999
Milisegundos025340230079999919709999

JavaScript

function validarRango(timestamp, precision = 'milisegundos') {
  const RANGOS = {
    segundos: { min: 0, max: 253402300799 },
    milisegundos: { min: 0, max: 253402300799999 },
    microsegundos: { min: 0, max: 253402300799999999n },
    nanosegundos: { min: 0n, max: 253402300799999999999n }
  };

  const rango = RANGOS[precision];
  if (!rango) {
    return { valido: false, error: 'Precisión desconocida' };
  }

  const valor = precision.includes('nano') ? BigInt(timestamp) : Number(timestamp);

  if (valor < rango.min || valor > rango.max) {
    return { 
      valido: false, 
      error: `Fuera de rango: ${rango.min} - ${rango.max}` 
    };
  }

  return { valido: true };
}

Validación de Rango de Negocio

from datetime import datetime, timezone

def validar_rango_negocio(timestamp_ms: int, config: dict) -> dict:
    """Valida que el timestamp esté dentro de rangos de negocio"""
    dt = datetime.fromtimestamp(timestamp_ms / 1000, tz=timezone.utc)

    # No puede ser en el futuro
    if config.get('no_futuro', True):
        if dt > datetime.now(timezone.utc):
            return {'valido': False, 'error': 'Timestamp en el futuro'}

    # No puede ser demasiado antiguo
    min_year = config.get('año_minimo', 2000)
    if dt.year < min_year:
        return {'valido': False, 'error': f'Año anterior a {min_year}'}

    # No puede ser demasiado en el futuro
    max_year = config.get('año_maximo', 2100)
    if dt.year > max_year:
        return {'valido': False, 'error': f'Año posterior a {max_year}'}

    return {'valido': True, 'datetime': dt}

Validación de Zona Horaria

Validar ISO 8601 con Zona Horaria

function validarIso8601(valor) {
  // Regex para ISO 8601 con zona horaria obligatoria
  const regex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d+)?(Z|[+-]\d{2}:\d{2})$/;

  if (!regex.test(valor)) {
    return { 
      valido: false, 
      error: 'Formato ISO 8601 inválido o falta zona horaria' 
    };
  }

  const fecha = new Date(valor);
  if (isNaN(fecha.getTime())) {
    return { valido: false, error: 'Fecha resultante inválida' };
  }

  return { valido: true, fecha };
}

Validar Identificador de Zona Horaria

from zoneinfo import ZoneInfo

def validar_zona_horaria(zona: str) -> dict:
    """Valida que sea un identificador IANA válido"""
    try:
        ZoneInfo(zona)
        return {'valido': True}
    except Exception as e:
        return {'valido': False, 'error': f'Zona horaria inválida: {zona}'}

# Ejemplo
print(validar_zona_horaria('America/New_York'))  # {'valido': True}
print(validar_zona_horaria('EST'))  # {'valido': False, ...} - ambiguo

Consideraciones de Seguridad

1. Prevenir Inyección

function sanitizarTimestamp(entrada) {
  // Solo permitir dígitos y caracteres ISO válidos
  const sanitizado = String(entrada).replace(/[^0-9TZ:.\-+]/g, '');

  if (sanitizado !== String(entrada)) {
    throw new Error('Caracteres inválidos detectados');
  }

  return sanitizado;
}

2. Prevenir Overflow

import sys

def validar_sin_overflow(valor: str) -> dict:
    """Previene overflow de enteros"""
    try:
        num = int(valor)

        # Verificar límites de 64-bit
        if num > sys.maxsize:
            return {'valido': False, 'error': 'Excede límite de entero'}

        if num < 0:
            return {'valido': False, 'error': 'Timestamps negativos no permitidos'}

        return {'valido': True, 'valor': num}
    except ValueError:
        return {'valido': False, 'error': 'No es un entero válido'}

3. Rate Limiting para Timestamps

// Prevenir manipulación de timestamps en requests
function validarTimestampRequest(timestamp, toleranciaMs = 30000) {
  const ahora = Date.now();
  const diff = Math.abs(ahora - timestamp);

  if (diff > toleranciaMs) {
    return { 
      valido: false, 
      error: `Timestamp fuera de tolerancia: ${diff}ms > ${toleranciaMs}ms` 
    };
  }

  return { valido: true };
}

Validador Completo

from datetime import datetime, timezone
from typing import Union

class ValidadorTimestamp:
    def __init__(self, config=None):
        self.config = config or {}

    def validar(self, valor: Union[str, int]) -> dict:
        """Validación completa de timestamp"""
        errores = []

        # 1. Formato
        formato = self._validar_formato(valor)
        if not formato['valido']:
            return formato

        # 2. Rango técnico
        rango = self._validar_rango(valor, formato['precision'])
        if not rango['valido']:
            return rango

        # 3. Rango de negocio
        negocio = self._validar_negocio(valor, formato['precision'])
        if not negocio['valido']:
            return negocio

        return {
            'valido': True,
            'precision': formato['precision'],
            'datetime': negocio['datetime']
        }

    def _validar_formato(self, valor):
        # ... implementación
        pass

    def _validar_rango(self, valor, precision):
        # ... implementación
        pass

    def _validar_negocio(self, valor, precision):
        # ... implementación
        pass

Resumen

  • Valida formato: Verifica longitud y caracteres
  • Valida rango: Técnico y de negocio
  • Valida zona horaria: Usa identificadores IANA
  • Considera seguridad: Sanitiza, previene overflow
  • Usa validadores completos: Combina todas las validaciones

¡Prueba nuestro Convertidor Unix Timestamp para validar timestamps!