chore: auto-commit (57 archivos)
- frontend/functions/core/format_datetime_short.md - frontend/functions/core/format_datetime_short.test.ts - frontend/functions/core/format_datetime_short.ts - frontend/functions/core/format_duration.md - frontend/functions/core/format_duration.test.ts - frontend/functions/core/format_duration.ts - frontend/functions/core/month_grid.md - frontend/functions/core/month_grid.test.ts - frontend/functions/core/month_grid.ts - frontend/functions/core/string_hash_palette.md - ... Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
package core
|
||||
|
||||
import "time"
|
||||
|
||||
// ParseDateOrDefault parses s as a date/datetime and returns the result.
|
||||
// Accepted formats: "2006-01-02" (YYYY-MM-DD) and time.RFC3339Nano.
|
||||
// Returns dflt when s is empty or does not match either format.
|
||||
// When endOfDay is true and the input matched YYYY-MM-DD, adds
|
||||
// 24*time.Hour - time.Nanosecond so the result is the last nanosecond of
|
||||
// that day (useful for inclusive end-of-range queries).
|
||||
// RFC3339Nano inputs are never adjusted regardless of endOfDay.
|
||||
func ParseDateOrDefault(s string, dflt time.Time, endOfDay bool) time.Time {
|
||||
if s == "" {
|
||||
return dflt
|
||||
}
|
||||
if t, err := time.Parse("2006-01-02", s); err == nil {
|
||||
if endOfDay {
|
||||
return t.Add(24*time.Hour - time.Nanosecond)
|
||||
}
|
||||
return t
|
||||
}
|
||||
if t, err := time.Parse(time.RFC3339Nano, s); err == nil {
|
||||
return t
|
||||
}
|
||||
return dflt
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
name: parse_date_or_default
|
||||
kind: function
|
||||
lang: go
|
||||
domain: core
|
||||
version: "1.0.0"
|
||||
purity: pure
|
||||
signature: "func ParseDateOrDefault(s string, dflt time.Time, endOfDay bool) time.Time"
|
||||
description: "Parsea s como fecha (YYYY-MM-DD) o datetime (RFC3339Nano). Retorna dflt si s esta vacio o no encaja en ninguno de los dos formatos. Si endOfDay es true y el formato fue YYYY-MM-DD, ajusta al ultimo nanosegundo del dia (util para rangos de fechas inclusivos por el final)."
|
||||
tags: [date, parse, time, default, range, YYYY-MM-DD, RFC3339Nano]
|
||||
uses_functions: []
|
||||
uses_types: []
|
||||
returns: []
|
||||
returns_optional: false
|
||||
error_type: ""
|
||||
imports:
|
||||
- time
|
||||
params:
|
||||
- name: s
|
||||
desc: "Cadena a parsear. Formatos aceptados: '2006-01-02' (YYYY-MM-DD) o RFC3339Nano. String vacio activa el valor por defecto."
|
||||
- name: dflt
|
||||
desc: "Valor time.Time a retornar cuando s esta vacio o no coincide con ningun formato soportado."
|
||||
- name: endOfDay
|
||||
desc: "Si es true y el input fue YYYY-MM-DD, suma 24h-1ns para apuntar al ultimo nanosegundo del dia. No tiene efecto sobre RFC3339Nano ni sobre el retorno de dflt."
|
||||
output: "time.Time parseado desde s, ajustado si endOfDay=true y formato YYYY-MM-DD; o dflt si s esta vacio o es invalido."
|
||||
tested: true
|
||||
tests:
|
||||
- "string vacio retorna dflt"
|
||||
- "formato invalido retorna dflt"
|
||||
- "YYYY-MM-DD sin endOfDay retorna inicio de dia"
|
||||
- "YYYY-MM-DD con endOfDay retorna ultimo nanosegundo del dia"
|
||||
- "RFC3339Nano sin endOfDay retorna timestamp exacto"
|
||||
- "RFC3339Nano con endOfDay no se ajusta"
|
||||
- "endOfDay false con dflt no lo modifica"
|
||||
test_file_path: "functions/core/parse_date_or_default_test.go"
|
||||
file_path: "functions/core/parse_date_or_default.go"
|
||||
source_repo: "https://github.com/egutierrez/fn_registry/apps/kanban"
|
||||
source_license: "private"
|
||||
source_file: "apps/kanban/backend/metrics.go"
|
||||
---
|
||||
|
||||
## Ejemplo
|
||||
|
||||
```go
|
||||
dflt := time.Now().UTC()
|
||||
|
||||
// Inicio de rango (incluye el dia completo desde las 00:00)
|
||||
from := ParseDateOrDefault("2024-01-01", dflt, false)
|
||||
|
||||
// Fin de rango (incluye hasta el ultimo nanosegundo del dia)
|
||||
to := ParseDateOrDefault("2024-01-31", dflt, true)
|
||||
|
||||
// Timestamp exacto desde RFC3339Nano (no se ajusta aunque endOfDay=true)
|
||||
ts := ParseDateOrDefault("2024-01-15T12:00:00Z", dflt, true)
|
||||
|
||||
// Valor invalido → dflt
|
||||
fallback := ParseDateOrDefault("no-es-fecha", dflt, false)
|
||||
```
|
||||
|
||||
## Notas
|
||||
|
||||
Unifica las dos funciones originales `parseDateOrDefault` y `parseEndDateOrDefault`
|
||||
de `apps/kanban/backend/metrics.go:132-156` en una sola funcion parametrica.
|
||||
`time.Parse` es deterministico, por lo que la funcion es pura aunque use el paquete `time`.
|
||||
@@ -0,0 +1,65 @@
|
||||
package core
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestParseDateOrDefault(t *testing.T) {
|
||||
dflt := time.Date(2000, 1, 1, 0, 0, 0, 0, time.UTC)
|
||||
|
||||
t.Run("string vacio retorna dflt", func(t *testing.T) {
|
||||
got := ParseDateOrDefault("", dflt, false)
|
||||
if !got.Equal(dflt) {
|
||||
t.Errorf("got %v, want %v", got, dflt)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("formato invalido retorna dflt", func(t *testing.T) {
|
||||
got := ParseDateOrDefault("no-es-fecha", dflt, false)
|
||||
if !got.Equal(dflt) {
|
||||
t.Errorf("got %v, want %v", got, dflt)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("YYYY-MM-DD sin endOfDay retorna inicio de dia", func(t *testing.T) {
|
||||
got := ParseDateOrDefault("2024-03-15", dflt, false)
|
||||
want := time.Date(2024, 3, 15, 0, 0, 0, 0, time.UTC)
|
||||
if !got.Equal(want) {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("YYYY-MM-DD con endOfDay retorna ultimo nanosegundo del dia", func(t *testing.T) {
|
||||
got := ParseDateOrDefault("2024-03-15", dflt, true)
|
||||
want := time.Date(2024, 3, 15, 23, 59, 59, 999999999, time.UTC)
|
||||
if !got.Equal(want) {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RFC3339Nano sin endOfDay retorna timestamp exacto", func(t *testing.T) {
|
||||
input := "2024-03-15T14:30:00.123456789Z"
|
||||
got := ParseDateOrDefault(input, dflt, false)
|
||||
want, _ := time.Parse(time.RFC3339Nano, input)
|
||||
if !got.Equal(want) {
|
||||
t.Errorf("got %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("RFC3339Nano con endOfDay no se ajusta", func(t *testing.T) {
|
||||
input := "2024-03-15T00:00:00Z"
|
||||
got := ParseDateOrDefault(input, dflt, true)
|
||||
want, _ := time.Parse(time.RFC3339Nano, input)
|
||||
if !got.Equal(want) {
|
||||
t.Errorf("RFC3339Nano should not be adjusted; got %v, want %v", got, want)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("endOfDay false con dflt no lo modifica", func(t *testing.T) {
|
||||
got := ParseDateOrDefault("", dflt, true)
|
||||
if !got.Equal(dflt) {
|
||||
t.Errorf("got %v, want %v", got, dflt)
|
||||
}
|
||||
})
|
||||
}
|
||||
Reference in New Issue
Block a user