---
title: Dates and time zones
description: Date and date-time fields, the space REST writes between date and time, and the Timezone header that returns date-times in your own zone.
canonical: https://developers.coevera.com/concepts/dates-and-time-zones/
section: concepts
verification: behaviour
lastVerified: 2026-10-15
publisher: Coevera
---

# Dates and time zones

**Answer:** Date fields are YYYY-MM-DD. Date-times come back in UTC with an offset, with a space between date and time in REST and a T in GraphQL. Send a Timezone header, such as Europe/Bratislava, to get them in that zone. Values you send without an offset are read as UTC, whatever the header says.

Two kinds of field hold time. Date fields hold a day; date-time fields hold an instant, which the
API writes in UTC unless you ask for your own time zone.

## Date and date-time fields

| Kind      | Example field                                         | REST                               | GraphQL                            |
| --------- | ----------------------------------------------------- | ---------------------------------- | ---------------------------------- |
| Date      | `closing_date` (shown in the app as **Closing date**) | `2026-12-15`                       | `2026-12-15`                       |
| Date-time | `created`, `modified`                                 | `2026-10-15 09:00:00.584362+00:00` | `2026-10-15T09:00:00.584362+00:00` |

- REST writes a **space** between the date and the time; GraphQL writes a `T`. A parser that
  insists on RFC 3339's `T` fails on REST values: replace the space with `T` before you parse.
- Date-times carry microseconds and an offset, `+00:00` unless you send a `Timezone` header.
- A date field has no time and no zone; the `Timezone` header does not change it.

## Read date-times in your time zone

Send a `Timezone` header and every date-time in the response comes back in that zone, with its
offset. The sample reads one opportunity twice, without the header and with
`Timezone: Europe/Bratislava`:

**REST · cURL**

```bash
COEVERA_BASE="https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}"

# No Timezone header: created and modified come back in UTC.
curl -sS --fail-with-body -G "$COEVERA_BASE/entities/Opportunities" \
  -d "filter[closing_date]=2026-12-15" \
  -d load-only=name,closing_date,created,modified \
  -d first=1 \
  -u "$COEVERA_API_KEY:$COEVERA_API_SECRET"
echo

# The same request with a Timezone header: the same instants, in that zone's offset.
curl -sS --fail-with-body -G "$COEVERA_BASE/entities/Opportunities" \
  -H "Timezone: Europe/Bratislava" \
  -d "filter[closing_date]=2026-12-15" \
  -d load-only=name,closing_date,created,modified \
  -d first=1 \
  -u "$COEVERA_API_KEY:$COEVERA_API_SECRET"
echo
```

**REST · TypeScript**

```ts
import { Buffer } from "node:buffer";
import { env } from "node:process";

const base = `https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}`;
const auth = Buffer.from(`${env.COEVERA_API_KEY}:${env.COEVERA_API_SECRET}`).toString("base64");

// The opportunity that closes on 2026-12-15, with its date and its two date-times.
const query = "filter[closing_date]=2026-12-15&load-only=name,closing_date,created,modified&first=1";

async function opportunities(headers: Record<string, string>) {
  const res = await fetch(`${base}/entities/Opportunities?${query}`, {
    headers: { Authorization: `Basic ${auth}`, ...headers },
  });
  const body = await res.json();
  if (!res.ok) throw new Error(`HTTP ${res.status} ${body.name}: ${body.message}`);
  return body.data;
}

// No Timezone header: created and modified come back in UTC.
console.log("UTC:", JSON.stringify(await opportunities({}), null, 2));

// The same request with a Timezone header: the same instants, in that zone's offset.
console.log("Europe/Bratislava:", JSON.stringify(await opportunities({ Timezone: "Europe/Bratislava" }), null, 2));
```

**REST · Python**

```python
import json
import os
import sys

import requests

BASE = "https://{region}.api.coevera.com/api/v100/rest/spaces/{space_id}"
session = requests.Session()
session.auth = (os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"])

# The opportunity that closes on 2026-12-15, with its date and its two date-times.
QUERY = "filter[closing_date]=2026-12-15&load-only=name,closing_date,created,modified&first=1"


def opportunities(headers):
    response = session.get(f"{BASE}/entities/Opportunities?{QUERY}", headers=headers, timeout=30)
    body = response.json()
    if not response.ok:
        sys.exit(f"HTTP {response.status_code} {body.get('name')}: {body.get('message')}")
    return body["data"]


# No Timezone header: created and modified come back in UTC.
print("UTC:", json.dumps(opportunities({}), indent=2))

# The same request with a Timezone header: the same instants, in that zone's offset.
print("Europe/Bratislava:", json.dumps(opportunities({"Timezone": "Europe/Bratislava"}), indent=2))
```

**GraphQL · cURL**

```bash
COEVERA_GRAPHQL="https://{region}.api.coevera.com/api/v100/app/space/{space_id}/graphql/public"

# The opportunity, with its date and its two date-times.
QUERY='{"query": "{ entities { opportunity { getByCriteria(first: 1, filter: { name: { icontains: [\"data platform rollout\"] } }) { edges { node { name closingDate created modified } } } } } }"}'

# No Timezone header: created and modified come back in UTC.
curl -sS --fail-with-body "$COEVERA_GRAPHQL" \
  -u "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  -H "Content-Type: application/json" \
  -d "$QUERY"
echo

# The same request with a Timezone header: the same instants, in that zone's offset.
curl -sS --fail-with-body "$COEVERA_GRAPHQL" \
  -u "$COEVERA_API_KEY:$COEVERA_API_SECRET" \
  -H "Content-Type: application/json" \
  -H "Timezone: Europe/Bratislava" \
  -d "$QUERY"
echo
```

**GraphQL · TypeScript**

```ts
import { Buffer } from "node:buffer";
import { env } from "node:process";

const endpoint = `https://{region}.api.coevera.com/api/v100/app/space/{space_id}/graphql/public`;
const auth = Buffer.from(`${env.COEVERA_API_KEY}:${env.COEVERA_API_SECRET}`).toString("base64");

// The opportunity, with its date and its two date-times.
const OPPORTUNITY = `{
  entities {
    opportunity {
      getByCriteria(first: 1, filter: { name: { icontains: ["data platform rollout"] } }) {
        edges { node { name closingDate created modified } }
      }
    }
  }
}`;

async function opportunities(headers: Record<string, string>) {
  const res = await fetch(endpoint, {
    method: "POST",
    headers: { Authorization: `Basic ${auth}`, "Content-Type": "application/json", ...headers },
    body: JSON.stringify({ query: OPPORTUNITY }),
  });
  const body = await res.json();
  // GraphQL reports errors in the body, often with HTTP 200: check both.
  if (!res.ok || body.errors) throw new Error(`HTTP ${res.status}: ${JSON.stringify(body.errors ?? body)}`);
  return body.data.entities.opportunity.getByCriteria.edges;
}

// No Timezone header: created and modified come back in UTC.
console.log("UTC:", JSON.stringify(await opportunities({}), null, 2));

// The same request with a Timezone header: the same instants, in that zone's offset.
console.log("Europe/Bratislava:", JSON.stringify(await opportunities({ Timezone: "Europe/Bratislava" }), null, 2));
```

**GraphQL · Python**

```python
import json
import os
import sys

import requests

ENDPOINT = (
    "https://{region}.api.coevera.com/api/v100/app/space/"
    "{space_id}/graphql/public"
)
AUTH = (os.environ["COEVERA_API_KEY"], os.environ["COEVERA_API_SECRET"])

# The opportunity, with its date and its two date-times.
OPPORTUNITY = """
{
  entities {
    opportunity {
      getByCriteria(first: 1, filter: { name: { icontains: ["data platform rollout"] } }) {
        edges { node { name closingDate created modified } }
      }
    }
  }
}
"""


def opportunities(headers):
    response = requests.post(ENDPOINT, json={"query": OPPORTUNITY}, auth=AUTH, headers=headers, timeout=30)
    body = response.json()
    # GraphQL reports errors in the body, often with HTTP 200: check both.
    if not response.ok or body.get("errors"):
        sys.exit(f"HTTP {response.status_code}: {json.dumps(body.get('errors', body))}")
    return body["data"]["entities"]["opportunity"]["getByCriteria"]["edges"]


# No Timezone header: created and modified come back in UTC.
print("UTC:", json.dumps(opportunities({}), indent=2))

# The same request with a Timezone header: the same instants, in that zone's offset.
print("Europe/Bratislava:", json.dumps(opportunities({"Timezone": "Europe/Bratislava"}), indent=2))
```

Without the header, `created` is in UTC:

**Recorded response · REST · 200 OK**

```json
{
  "success": true,
  "total": 1,
  "page_info": {
    "start_cursor": "WyIwMDAwMDAwMC0wMDAwLTQwMDAtYTAwMC0wMDAwMDAwMDAwMDEiXQ==",
    "end_cursor": "WyIwMDAwMDAwMC0wMDAwLTQwMDAtYTAwMC0wMDAwMDAwMDAwMDEiXQ==",
    "has_previous_page": false,
    "has_next_page": false
  },
  "data": [
    {
      "modified": "2026-10-15 09:41:21.513848+00:00",
      "created": "2026-10-15 09:00:00.000000+00:00",
      "closing_date": "2026-12-15",
      "name": "Northwind data platform rollout"
    }
  ]
}
```

**Recorded response · GraphQL · 200 OK**

```json
{
  "data": {
    "entities": {
      "opportunity": {
        "getByCriteria": {
          "edges": [
            {
              "node": {
                "name": "Northwind data platform rollout",
                "closingDate": "2026-12-15",
                "created": "2026-10-15T09:00:00.000000+00:00",
                "modified": "2026-10-15T09:41:21.513848+00:00"
              }
            }
          ]
        }
      }
    }
  }
}
```

_Recorded on 2026-10-15 against API 6.5.2 in the docs sandbox, de-identified._

With it, the same instant comes back at `+02:00`, the offset Bratislava had on the day of the
recording; `closing_date` is unchanged:

**Recorded response · REST · 200 OK**

```json
{
  "success": true,
  "total": 1,
  "page_info": {
    "start_cursor": "WyIwMDAwMDAwMC0wMDAwLTQwMDAtYTAwMC0wMDAwMDAwMDAwMDEiXQ==",
    "end_cursor": "WyIwMDAwMDAwMC0wMDAwLTQwMDAtYTAwMC0wMDAwMDAwMDAwMDEiXQ==",
    "has_previous_page": false,
    "has_next_page": false
  },
  "data": [
    {
      "modified": "2026-10-15 11:41:21.513848+02:00",
      "created": "2026-10-15 11:00:00.000000+02:00",
      "closing_date": "2026-12-15",
      "name": "Northwind data platform rollout"
    }
  ]
}
```

**Recorded response · GraphQL · 200 OK**

```json
{
  "data": {
    "entities": {
      "opportunity": {
        "getByCriteria": {
          "edges": [
            {
              "node": {
                "name": "Northwind data platform rollout",
                "closingDate": "2026-12-15",
                "created": "2026-10-15T11:00:00.000000+02:00",
                "modified": "2026-10-15T11:41:21.513848+02:00"
              }
            }
          ]
        }
      }
    }
  }
}
```

_Recorded on 2026-10-15 against API 6.5.2 in the docs sandbox, de-identified._

The header takes these forms:

| Form                          | Example                                 | Offset on 2026-10-15                        |
| ----------------------------- | --------------------------------------- | ------------------------------------------- |
| IANA zone name                | `Europe/Bratislava`, `America/New_York` | `+02:00`, `-04:00`: daylight saving applies |
| Windows zone name             | `Central Europe Standard Time`          | `+02:00`                                    |
| `UTC` or `GMT` with an offset | `UTC+2`, `UTC-03:30`, `GMT-5`           | `+02:00`, `-03:30`, `-05:00`                |
| Minutes east of UTC           | `60`                                    | `+01:00`                                    |
| `UTC`                         | `UTC`                                   | `+00:00`                                    |

A one-word abbreviation such as `CET`, or a name the API does not know, is ignored without an
error: the response stays in UTC. GraphQL honours the header too.

## Send date-times

- A date-time you send without an offset is read as UTC, even when you send a `Timezone` header.
  `filter[created]=2026-10-15 05:06:36` with `Timezone: Europe/Bratislava` means `05:06:36` in
  UTC, not in Bratislava. Send an offset, `2026-10-15T07:06:36+02:00`, or convert to UTC first.
- Filters accept a space or a `T` between date and time, and a date alone on a date-time field:
  `filter[created]=2026-10-15&filter-op[created]=gte`.
- Filter a date field with `YYYY-MM-DD`: `filter[closing_date]=2026-12-15`. GraphQL has no filter
  on `closingDate`.
- `created` and `modified` can be set on create, for example when you import records with their
  original dates; the values you send are stored. A value more than one day after the time of the
  request, on a create or an update, is ignored: the write succeeds and the field is set as if
  you had not sent it. To store such a value, add `validation-level` bit 8
  ([validation](/concepts/validation/#the-bits)).

## Limits

| Limit                               | Details                                                                          |
| ----------------------------------- | -------------------------------------------------------------------------------- |
| Zone abbreviations                  | `CET`, `EST` and other one-word names are ignored; use an IANA name              |
| Input without an offset             | Read as UTC, whatever the `Timezone` header says                                 |
| Separator                           | REST writes a space, GraphQL a `T`                                               |
| Date fields                         | No zone; the header does not apply                                               |
| `created`, `modified` in the future | More than one day ahead is ignored on write, unless `validation-level` has bit 8 |
