> ## Documentation Index
> Fetch the complete documentation index at: https://developers.luccasoftware.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Data Types & Formatting

> The Lucca API normalizes the formatting of some data types.

## Dates, Date-Times & Date-Time-Offsets

**A date-time represents a point in the time scale outside of any timezone. A date without time represents a day of the calendar outside of any timezone. A date-time-offset represents a point in the time scale based on Universal Coordinated Time (UTC).**

<Warning>
  Please note that the Lucca API enforces strong validation of each type. You may receive an error when trying to send a date in place of a date-time, or if you forget to send the offset of a date-time-offset. Default values are disabled in order to avoid unexpected side-effects.
</Warning>

Dates and date-times are formatted according to the ISO 8601 and <a href="https://www.rfc-editor.org/rfc/rfc3339" target="_blank">RFC 3339</a> standards, whose ABNF grammar is the following:

<CodeGroup>
  ```abnf ABNF Grammar theme={null}
  date-fullyear       = 4DIGIT
  date-month          = 2DIGIT  ; 01-12
  date-mday           = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on month/year
  time-hour           = 2DIGIT  ; 00-23
  time-minute         = 2DIGIT  ; 00-59
  time-second         = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second rules
  time-secfrac        = "." 1*DIGIT
  time-numoffset      = ("+" / "-") time-hour ":" time-minute
  time-offset         = "Z" / time-numoffset

  partial-time        = time-hour ":" time-minute ":" time-second
                      [time-secfrac]
  full-date           = date-fullyear "-" date-month "-" date-mday
  full-time           = partial-time time-offset

  date-time           = full-date "T" full-time
  floating-date-time  = full-date "T" partial-time
  ```
</CodeGroup>

<br />

<Info>
  The `Z` character in the `time-offset` part of the string is equivalent to a `+00:00` timezone offset. In other words, in indicates the date-time is UTC.
</Info>

<Tip>
  Time is always 24-hour, i.e. there is no "AM" or "PM" part.
</Tip>

| Type                   | Description                                                                                                              | ABNF           | Example                                                          |
| :--------------------- | :----------------------------------------------------------------------------------------------------------------------- | :------------- | :--------------------------------------------------------------- |
| `Date`                 | Date of a day.                                                                                                           | `full-date`    | `2023-01-01`                                                     |
| `Date-Time` (Local)    | Timezoned date and time.                                                                                                 | `full-time`    | `2023-01-01T09:45:23.0001Z` :br `2023-01-01T07:45:23.0001+02:00` |
| `Date-Time` (Floating) | Date-time value that isn't tied to a specific time zone. It's occurs at the same displayed local time, wherever you are. |                |                                                                  |
| `Time` (Local)         | Timezoned time value.                                                                                                    | `full-time`    | `07:30Z`                                                         |
| `Time` (Floating)      | Time value that isn't tied to a specific time zone (e.g: the time of your alarm clock).                                  | `partial-time` | `07:30`                                                          |

<Info>
  Most date typed properties are suffixed with "On", and most date-time typed properties with "At". For example: `(date-time) createdAt`, `(date) occursOn`, etc...
</Info>

***

## Date Ranges

<CodeGroup>
  ```http Date after 2024-01-01 theme={null}
  GET /lucca-api/employments?endsOn.between=2024-01-01--.. HTTPS/2
  Host: example.ilucca.net
  Api-Version: {API_VERSION}
  Authorization: Bearer {ACCESS_TOKEN}
  Accept: application/json
  Accept-Encoding: gzip, br
  ```

  ```http Date before 2024-01-01 theme={null}
  GET /lucca-api/employments?endsOn.between=..--2024-01-01 HTTPS/2
  Host: example.ilucca.net
  Api-Version: {API_VERSION}
  Authorization: Bearer {ACCESS_TOKEN}
  Accept: application/json
  Accept-Encoding: gzip, br
  ```

  ```http Date in Jan. 2024 theme={null}
  GET /lucca-api/employments?endsOn.between=2024-01-01--2024-01-31 HTTPS/2
  Host: example.ilucca.net
  Api-Version: {API_VERSION}
  Authorization: Bearer {ACCESS_TOKEN}
  Accept: application/json
  Accept-Encoding: gzip, br
  ```
</CodeGroup>

<Tip>
  Date ranges are most often used in query parameters in order to filter out results based on a
  [date attribute value being comprised in a given range](./filtering#dates-date-times-and-date-time-offsets).
</Tip>

Depending on the type of date, there can be:

* a *date-range* `2023-01-01--2023-01-31` represents the interval between two dates, outside of any timezone. Here, both the start and end date are **included**.
* a *date-time-range* `2023-01-01T00:00:00--2023-01-02T00:00:00` represents the interval between two points in the time scale, outside of any timezone. Here, the end date is **NOT included**.
* a *date-time-offset-range* `2023-01-01T00:00:00+02:00--2023-01-02T00:00:00+02:00`represents the interval between two points in the time scale, defined in reference to UTC. Here, the end date is **NOT included**.

In conformance with ISO 8601, a date range can be serialized as a single string that contains both dates, separated by the "--" characters.

<Info>
  In the spec, dates can be separated with the "/" (slash) character, but this could break URLs when serializing ranges as query parameters values `?date=2023-01-01/2023-01-31`, so the Lucca API does not officially support it. Besides, the Lucca API does not support ranges defined as a date and a duration either.
</Info>

Open-handed ranges can be defined with the `".."` characters:

* `..--2023-01-01`: until Jan. 1<sup>st</sup> 2023 ;
* `2023-01-01--..`: since Jan. 1<sup>st</sup> 2023.

The ABNF grammar for such ranges is:

<CodeGroup>
  ```abnf ABNF theme={null}
  date-fullyear         = 4DIGIT
  date-month            = 2DIGIT  ; 01-12
  date-mday             = 2DIGIT  ; 01-28, 01-29, 01-30, 01-31 based on month/year
  time-hour             = 2DIGIT  ; 00-23
  time-minute           = 2DIGIT  ; 00-59
  time-second           = 2DIGIT  ; 00-58, 00-59, 00-60 based on leap second rules
  time-secfrac          = "." 1*DIGIT
  time-numoffset        = ("+" / "-") time-hour ":" time-minute
  time-offset           = "Z" / time-numoffset

  iso-date              = date-fullyear "-" date-month "-" date-mday
  iso-date-time         = iso-date "T" time-hour ":" time-minute ":" time-second [time-secfrac]
  iso-date-time-offset  = iso-date-time time-offset

  date-range                  = (iso-date / "..") "--" (iso-date / "..")
  date-time-range             = (iso-date-time / "..") "--" (iso-date-time / "..")
  date-time-offset-ranges     = (iso-date-time-offset / "..") "--" (iso-date-time-offset / "..")
  ```
</CodeGroup>

***

## Durations (time intervals)

**A duration represents the length of the interval between two points in the time scale**.

**Duration ISO value**

Same as with dates and date-times, durations (or time intervals) also conform to the ISO 8601 standard, whose ABNF grammar is:

<CodeGroup>
  ```abnf ABNF Grammar theme={null}
  dur-second        = 1*DIGIT "S"
  dur-minute        = 1*DIGIT "M" [dur-second]
  dur-hour          = 1*DIGIT "H" [dur-minute]
  dur-time          = "T" (dur-hour / dur-minute / dur-second)
  dur-day           = 1*DIGIT "D"
  dur-week          = 1*DIGIT "W"
  dur-month         = 1*DIGIT "M" [dur-day]
  dur-year          = 1*DIGIT "Y" [dur-month]
  dur-date          = (dur-day / dur-month / dur-year) [dur-time]
  duration          = "P" (dur-date / dur-time / dur-week)
  ```
</CodeGroup>

For example, `P2DT12H30M23S` indicates "2 days, 12 hours, 30 minutes and 23 seconds".

<Warning>
  Durations can be negative, in which case it is prefixed with a "-" (hyphen) character.
</Warning>

**Unit & Value**

In time management, work durations are often handled either:

* as a number of hours,
* or as a fraction of days.

For instance, in France, some managers don't have their work duration expressed in hours, but rather in a number of days. Another example would be consultants working on projects for their clients: often, the company tracks their times as a fraction of days rather than as a number of hours, in order to make billing easier (they bill by the day rather than by the hour).

This is why work-durations are more complex objects than a simple ISO string:

<CodeGroup>
  ```json Half a day theme={null}
  {
    "iso": "PT12H",
    "value": "0.5",
    "unit": "days"
  }
  ```

  ```json 12 hours theme={null}
  {
    "iso": "PT12H",
    "value": "12",
    "unit": "hours"
  }
  ```
</CodeGroup>

<br />

<Tip>
  If you only need to display a work-duration, then you can simply use the `value` property, followed by the `unit`. But if calculations are needed, it is recommended to parse the `iso` property, as the `value` can be subject to rounding (e.g. "1h20" gives a decimal value of "1.3333...").
</Tip>

***

## Enumerations

**In the Lucca API, enumerations are string typed, non-nullable, and must be considered extensible.**

You should be aware of the extensible nature of all enumerations. It means that adding a new value to an existing enumeration is not considered a breaking change in the Lucca API. Therefore, your code should prepare for it.
