# `Estructura.Nested.Type.TimeSeries`
[🔗](https://github.com/am-kantox/estructura/blob/v1.13.0/lib/estructura/nested/type/scaffold/time_series.ex#L1)

`Estructura` type scaffold for creating time series types, where the value is
  predictable changing with a time.

This module provides a way to create custom types containing the timestamp,
  “static” values, changing randomly, and the time series type.

The good example of such a type would be a currency exchange rate.

## Usage

There are two ways to use this type scaffold:

### 1. Using the module directly

Unlike other scaffolded modules, this one is supposed to be created as a standalone
  module using `Estructura.Nested.Type.TimeSeries`.

### 2. Using the `use` macro

    defmodule Rate do
      use Estructura.Nested.Type.TimeSeries,
        series: [
          value: {:oscillating, average: 1.0, amplitude: 0.3, outliers: 0.4}
        ],
        timestamp: :timestamp
    end

## Configuration Options

The scaffold accepts the following options:

- `:series` - (required) List of valid values for the time series object
- `:timestamp` - (optional) the type of timestamp field, allowed: `:mototonic`, `:timestamp`, default `:timestamp` 
- `:coercer` - (optional) Function to coerce input values
- `:encoder` - (optional) Function to encode values for JSON

### Example with Custom Coercion

    defmodule Rate do
      use Estructura.Nested.Type.TimeSeries,
        series: [
          value: {:oscillating, average: 1.0, amplitude: 0.3, outliers: 0.4}
        ],
        timestamp: :timestamp,
        coercer: fn
          %Decimal{} = decimal -> {:ok, Decimal.to_float(decimal)}
          integer when is_integer(integer) -> {:ok, 1.0 * integer}
          float when is_float(float) -> {:ok, float}
          other -> {:error, "Cannot coerce #{inspect(other)} to TimeSeries object"}
        end
    end

### Example with Custom JSON Encoding

    defmodule Rate do
      use Estructura.Nested.Type.TimeSeries,
        series: [
          value: {:oscillating, average: 1.0, amplitude: 0.3, outliers: 0.4}
        ],
        encoder: fn rate, opts -> Jason.Encode.map(Map.from_struct(rate), opts) end
    end

## Generated Functions

The scaffold implements the `Estructura.Nested.Type` behaviour and provides:

- `generate/1` - Generates random values from the enum for testing
- `coerce/1` - Attempts to convert input into a valid enum value
- `validate/1` - Ensures a value is part of the enum

### Generation Options

The `generate/1` function accepts:
- `:only` - values to generate for (default: all)
- `:except` - values to exclude from generation

```elixir
Rate.generate() |> Enum.take(1)
#⇒ %Rate{
#    currency: :USD,
#    counter_currency: :EUR,
#    timestamp: ~U[2025-7-6T12:00:00Z],
#    value: 1.1
#  }
```

# `__using__`
*macro* 

Implements the enum type directly in the current module.

## Options

See the module documentation for available options.

## Examples

```elixir
defmodule RateType do
  use Estructura.Nested.Type.TimeSeries,
    series: [value: {:oscillating, &RateType.rate_config/1}],
    timestamp: :timestamp

  def rate_config(_currencies) do
    [average: 1.2, amplitude: 0.3, outliers: 0.2]
  end
end
```

# `type_module_ast`

Creates a new enum type module with the given name and options.

## Options

See the module documentation for available options.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
