Discussions

Ask a Question
Back to all

Absence period API incorrectly handles timezones (entries not retrievable via search)

When creating absence periods with UTC timestamps, the API is incorrectly converting or ignoring timezone information. This leads to absence entries being created with shifted times and makes them impossible to retrieve with standard search queries.

Steps to reproduce:

  1. Create an absence with this request:
{
  "person": {
    "id": "17479948"
  },
  "starts_from": {
    "date_time": "2025-08-19T00:00:00Z"
  },
  "ends_at": {
    "date_time": "2025-08-19T01:00:00Z"
  },
  "absence_type": {
    "id": "fea2d41b-4ed0-44fe-841b-ce9b293d35d4"
  },
  "comment": "Test"
}
  1. The API responds with:
{
  "absence_type": {
    "id": "fea2d41b-4ed0-44fe-841b-ce9b293d35d4"
  },
  "approval": {
    "status": "APPROVED"
  },
  "comment": "Test",
  "created_at": "2025-08-19T15:17:38.171372Z",
  "ends_at": {
    "date_time": "2025-08-19T01:00:00", // <- wrong time for the stated timezone below
    "type": null
  },
  "id": "ca8f3f2c-b693-4dea-982e-a5b031108f91",
  "person": {
    "id": "17479948"
  },
  "starts_from": {
    "date_time": "2025-08-19T00:00:00", // <- wrong time for the stated timezone below
    "type": null
  },
  "timezone_id": "Europe/Berlin", // <- ???
  "updated_at": "2025-08-19T15:17:38.171372Z"
}

Issue:

  • The API strips the Z (UTC indicator) and stores the times as if they were local time in Europe/Berlin.
  • In reality, 2025-08-19T00:00:00Z = 2025-08-19T02:00:00 Berlin time.
  • As a result, the entry is actually stored at the wrong local time.

Impact:
When querying with:

GET https://api.personio.de/v2/absence-periods?starts_from.date_time.gte=2025-08-19T00:00:00Z&ends_at.date_time.lte=2025-08-20T00:00:00Z

…the absence created above is not returned, because the API has effectively shifted it by -2h when saving.

Moreover the Attendance API does only take non Z Dates for search e.g. https://api.personio.de/v2/attendance-periods?limit=100&start.date_time.gte=2025-08-15T00:00:00&end.date_time.lte=2025-08-16T00:00:00

So another inconsistency...

Expected behavior:

  • API should correctly store and return absence periods in line with provided UTC timestamps.
  • Absence periods should be consistently retrievable using the same UTC-based filters.
  • Behavior should be consistent across all Personio APIs (Absence, Attendance, etc.).

Actual behavior:

  • API silently converts/removes UTC timezone info.
  • Entries are shifted and not found by queries, leading to major inconsistencies.

Severity: Major
This breaks fundamental use of the API since absence records cannot be reliably created, queried, or reconciled.