# Calendario

> Una cuadrícula del mes para elegir un día, un rango o varios días, siempre a la vista. Componente de Pyzed para GUIs en Python.

Source: https://albakore.github.io/pyzed/es/library/calendar/

:::tip[En pocas palabras]
Un mes en pantalla, como un calendario de pared, donde haces clic en los días para elegirlos.
:::

`ui.Calendar` muestra uno o varios meses. `mode` elige un solo día (`"single"`), un rango (`"range"`, dos clics) o cualquier número de días (`"multiple"`, cada clic marca o desmarca uno). La cabecera cambia a una cuadrícula de meses y luego de años para saltar lejos, y las flechas del teclado mueven el día enfocado (Re Pág/Av Pág por meses, Enter lo elige). Los selectores de esta sección abren uno de estos en una ventana flotante.

`ui.Calendar` · Categoría: [Fechas y horas](https://albakore.github.io/pyzed/es/library/#fechas-y-horas) · [Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#calendar)

**Código:**

```python
pz.row([
    ui.Calendar(value="2026-10-22", today_button=True, on_change=on_change),
    ui.Calendar(value=("2026-10-05", "2026-10-14"), mode="range", disabled=["weekend"], on_change=on_change),
], spacing=24)
```

:::note[Nuevo]
Este componente se añadió hace poco. Cuéntanos qué tal te funciona en el [gestor de incidencias](https://github.com/albakore/pyzed/issues).
:::

## Cuándo usarlo

- En un panel lateral o un tablero, donde el calendario se queda a la vista.
- `first_weekday` (`"monday"`, `"sunday"`...) y `week_numbers=True` siguen las costumbres locales.
- Dentro de un campo de formulario, usa [Selector de fecha](https://albakore.github.io/pyzed/es/library/date-picker/).

## Uso

```python
import pyzed as pz
from pyzed import ui

class Planner(pz.App):
    def __init__(self):
        self.days = []

    def view(self):
        return pz.row([
            ui.Calendar(value=self.days, mode="multiple", week_numbers=True,
                        on_change=lambda e: setattr(self, "days", e.value)),
            pz.column([ui.label(ui.format_date(d, "ddd D MMM")) for d in self.days], spacing=4),
        ], spacing=16)
```

## Variantes

:::note[Sobre estas capturas]
Cada captura la graba pyzed mismo, fuera de pantalla a 2x, en One Dark o One Light según el tema de este sitio, y recortada al componente para que se vea a su tamaño real. El puntero pasa por encima, pulsa o escribe en él; un componente que no reacciona al puntero recorre algunos temas. Con movimiento reducido ves el primer fotograma. Abre **Código** bajo una captura para ver el fragmento que la dibuja; los nombres libres como `on_save` son tus propios callbacks.
:::

### Modo

```python
ui.Calendar(value="2026-10-22", on_change=on_change)
```

```python
ui.Calendar(value=("2026-10-05", "2026-10-14"), mode="range", on_change=on_change)
```

```python
ui.Calendar(value=["2026-10-06", "2026-10-13", "2026-10-20", "2026-10-27"], mode="multiple", on_change=on_change)
```

### Opciones

```python
ui.Calendar(value="2026-10-22", week_numbers=True, first_weekday="monday", on_change=on_change)
```

```python
ui.Calendar(value="2026-10-22", first_weekday="sunday", on_change=on_change)
```

```python
ui.Calendar(value="2026-10-22", min="2026-10-08", max="2026-10-28", disabled=["weekend"], on_change=on_change)
```

```python
ui.Calendar(value="2026-10-22", show_outside=False, today_button=True, on_change=on_change)
```

### Vistas

Un clic en el título pasa a los meses, y otro a los años.

```python
ui.Calendar(value=("2026-10-26", "2026-11-04"), mode="range", months=2, on_change=on_change)
```

```python
ui.Calendar(value="2026-10-22", on_change=on_change)
```

```python
ui.Calendar(value="2026-10-22", on_change=on_change)
```

## Eventos

Calendario tiene **2 eventos propios**, en la tabla de abajo. Como todo widget, también tiene los **18 eventos comunes** (`click`, `double_click`, `right_click`, `mouse_enter`, `drag`, `key_down`, `resize`…), que se conectan con `.on(...)`: mira [Eventos](https://albakore.github.io/pyzed/es/guides/events/) y [Eventos de cada componente](https://albakore.github.io/pyzed/es/library/events/).

Es un `pz.Component`, así que también lanza `on_mount` y `on_unmount`, y sus handlers reciben un `pz.Event` cuyo `value` trae el dato.

| Evento | El handler recibe | Cuándo |
| --- | --- | --- |
| `on_change` | `(event)` | Recibe `event.value` (una fecha, una tupla o una lista). |
| `on_month` | `(event)` | Recibe `event.value`, el `(año, mes)` que se muestra. |

**El handler recibe** es lo que Pyzed le pasa a tu función: `()` es nada. Cualquier handler también puede ser un mensaje (un valor que no se puede llamar), que va a `update()`.

### Manejar los eventos

Los mismos eventos escritos de tres formas. **Imperativa**: métodos de la app que cambian `self`. **Declarativa**: los handlers producen mensajes y un único `update()` decide. **Funcional**: una función pura dibuja un estado inmutable y pide cambios con `set_state(...)`. Mira [Imperativo, declarativo y funcional](https://albakore.github.io/pyzed/es/guides/code-styles/).

**Imperativo:**

```python
class Planner(pz.App):
    def __init__(self):
        self.days = []

    def changed(self, event):            # on_change: the list of days ("multiple" mode)
        self.days = event.value

    def view(self):
        return pz.row([
            ui.Calendar(value=self.days, mode="multiple", on_change=self.changed),
            ui.label(f"{len(self.days)} days"),
        ], spacing=16)
```

**Declarativo:**

```python
from dataclasses import dataclass

@dataclass
class Day:
    value: object

class Planner(pz.App):
    day = None

    def update(self, message):
        match message:
            case Day(value):
                self.day = value

    def view(self):
        return ui.Calendar(value=self.day, today_button=True, on_change=lambda e: Day(e.value))
```

**Funcional:**

```python
from dataclasses import dataclass

@dataclass(frozen=True)
class State:
    stay: tuple = ("2026-10-05", "2026-10-09")

def view(state, set_state):
    return ui.Calendar(value=state.stay, mode="range", months=2, on_change=lambda e: set_state(stay=e.value))
```

## Propiedades y API

### `ui.Calendar`

```python
class Calendar
```

Un componente con un mes donde elegir un día (`mode="single"`), un rango (`"range"`: el primer clic lo empieza y el segundo lo termina) o varios días (`"multiple"`). El título abre una cuadrícula de meses y después de años. Tras un clic recibe el teclado: las flechas mueven, Enter elige y Re Pág/Av Pág cambian de mes. Ver la página [Calendario](https://albakore.github.io/pyzed/es/library/calendar/).

| Propiedad | Por defecto | Descripción |
| --- | --- | --- |
| `value` | `None` | Una fecha (`datetime.date` o `"2026-10-22"`), un par `(inicio, fin)` o una lista de fechas, según `mode`. |
| `mode` | `"single"` | `"single"`, `"range"` o `"multiple"`. |
| `min` | `None` | El primer día que se puede elegir. |
| `max` | `None` | El último día que se puede elegir. |
| `disabled` | `()` | Días que no se pueden elegir: fechas, nombres de día en inglés (`"sunday"`) o `"weekends"`. |
| `first_weekday` | `"monday"` | `"monday"`, `"sunday"` o `"saturday"`. |
| `months` | `1` | Meses que se ven uno al lado del otro. |
| `week_numbers` | `False` | Muestra el número de semana ISO de cada fila. |
| `show_outside` | `True` | Muestra los días de los meses vecinos. |
| `today_button` | `False` | Añade un enlace Hoy. |

Eventos: `on_change`, `on_month` ([eventos](#eventos)).

[Referencia completa →](https://albakore.github.io/pyzed/es/reference/ui/#calendar)

## Relacionados

- [Selector de fecha](https://albakore.github.io/pyzed/es/library/date-picker/): Un campo de fecha con un calendario desplegable, en el formato que elijas.
- [Selector de rango de fechas](https://albakore.github.io/pyzed/es/library/date-range-picker/): Dos fechas en un campo, con dos meses lado a lado y rangos rápidos.
