Timezone Converter
time.convert_timezone
Overview
Converts an instant or a zone-less local date-time from one IANA time zone to another through java.time. Daylight-saving edge cases are resolved by a policy the caller chooses, never silently: a local time that occurs twice is resolved by 'ambiguityPolicy' and one that never occurs by 'gapPolicy', and the outcome is reported in 'transition'. Legacy three-letter abbreviations such as CST are rejected because they are ambiguous. The result depends on the IANA tzdb version, which is reported in _meta.
Timezone conversion is not offset arithmetic — we convert through an instant and resolve DST overlaps and gaps under policies you choose.
Reliability
Same input, same answer for a given IANA time-zone database version, which we report as _meta.tzdbVersion — pin it if you compare stored conversions, because a database update can legitimately change a historical or future offset. We read no clock, so there is no now here. Conversion always goes through an instant rather than by adding an offset difference to a local field, which is where the classic one-hour errors come from. TIMEZONE_UNKNOWN — trigger: a zone we cannot resolve, which covers a typo, a three-letter abbreviation such as CST or EST, a fixed offset such as +02:00, and the case where dateTime has no offset and you sent no fromZone at all; retryable: no, the same value always fails; next: send a region-based identifier like Europe/Brussels or America/New_York, or UTC, and make sure fromZone is present whenever your dateTime carries no offset. TIMEZONE_OFFSET_CONFLICT — trigger: your dateTime carries an offset that the fromZone you named does not use at that local time, which usually means the offset was written by hand or the zone is wrong; retryable: no; next: drop the offset and let fromZone decide, drop fromZone and let the offset stand alone, or correct whichever of the two is wrong — the error message lists the offsets that zone does use. DATETIME_AMBIGUOUS — trigger: a zone-less local time that happens twice because the clocks went back, while ambiguityPolicy is reject; retryable: no, it is a genuine question about your data; next: decide which pass you meant and resend with ambiguityPolicy earlier or later, or send the reading with its offset so there is nothing to decide. DATETIME_NONEXISTENT — trigger: a zone-less local time that never happened because the clocks went forward, while gapPolicy is reject; retryable: no; next: resend with gapPolicy shift_forward or shift_backward, or correct the reading — a time in the gap is usually a sign the value was computed rather than observed.
Context footprint
One call replaces zone-rule lookups an agent cannot perform from memory; the response is two readings and a transition verdict. A successful call costs 1 execution credit.
When to use it
When you have a concrete date-time and need the same instant in another IANA zone with DST edge cases decided explicitly.
Do not use to guess a zone from prose, to parse free-text dates (use time.parse_datetime first), or to expand a recurring series.
Scope
Non-goals
- Does not infer a zone from a city name, a country, or a phone prefix
- Does not resolve legacy three-letter abbreviations — CST, IST, and EST are ambiguous and are rejected
- Does not read the system clock; there is no 'now' in this skill
- Does not convert a duration or a recurring series (use time.generate_recurrence)
- Does not format for display in a locale (the output is ISO-8601)
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
How we handle your data
What this means
This skill may receive sensitive content, but it does not target sensitive data and returns only a structured non-sensitive result.
Squillify guarantees
- Runs inside Squillify
- This skill runs inside Squillify.
- Payloads are not sent to an external service by this skill.
- Squillify does not permanently store submitted payloads.
- Telemetry records metadata only, not submitted content.
- Submitted payloads are not used for training.
- Submitted payloads are not reviewed by humans.
- This skill does not target sensitive data.
- The response does not contain submitted content.
Your responsibility
Squillify does not determine whether submitted content is sensitive. Your application is responsible for deciding what data it is allowed to submit. Your application is responsible for securing the response.
Input schema
| Field | Type | Required | Description |
|---|---|---|---|
| dateTime | string | Yes | ISO-8601 local or offset date-time. |
| toZone | string | Yes | Target IANA region zone or UTC. |
| fromZone | string | No | Source IANA region zone or UTC; omit it when dateTime already carries an offset. |
| ambiguityPolicy | string | No | DST overlap rule; omit it for earlier. |
| gapPolicy | string | No | DST gap rule; omit it for shift_forward. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| source | object | Yes | One closed zoned date-time reading with dateTime, zone, and the UTC offset in force. |
| target | object | Yes | One closed zoned date-time reading with dateTime, zone, and the UTC offset in force. |
| epochMillis | integer | Yes | Converted Unix epoch milliseconds. |
| transition | object | Yes | Closed daylight-saving resolution receipt with the transition kind and the policy that resolved it. |
| _meta | object | No | Closed applied tzdb receipt naming the IANA tzdbVersion actually used for this conversion. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"time.convert_timezone","input":{"dateTime":"2026-03-15T14:30:00","fromZone":"Europe/Brussels","toZone":"America/New_York"}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("time.convert_timezone", {"dateTime":"2026-03-15T14:30:00","toZone":"America/New_York","fromZone":"Europe/Brussels"});Errors
| Code | HTTP | Retryable | Description |
|---|---|---|---|
| VALIDATION_ERROR | 400 | No | The request payload failed schema validation. |
| UNAUTHORIZED | 401 | No | Missing or invalid API key. |
| SKILL_NOT_ACCESSIBLE | 403 | No | The API key is not granted access to this skill. |
| SKILL_NOT_AVAILABLE_FOR_PLAN | 403 | No | This skill is not included in your current plan. |
| PLAN_ELIGIBILITY_UNAVAILABLE | 503 | Yes | Plan eligibility could not be decided. Retry after backoff. |
| SKILL_NOT_FOUND | 404 | No | The requested skill or version does not exist. |
| TENANT_RATE_LIMITED | 429 | Yes | Request rate limit exceeded. Retry after backoff. |
| QUOTA_EXCEEDED | 429 | Yes | Plan quota exhausted. Retryable once the quota period resets. |
| EXECUTION_TIMEOUT | 504 | Yes | Execution exceeded the allowed time budget. |
| TIMEZONE_UNKNOWN | 400 | No | The request payload failed this skill's input validation. |
| TIMEZONE_OFFSET_CONFLICT | 400 | No | The request payload failed this skill's input validation. |
| DATETIME_AMBIGUOUS | 412 | No | The input is valid but cannot be processed as-is. |
| DATETIME_NONEXISTENT | 412 | No | The input is valid but cannot be processed as-is. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not infer a zone from a city name, a country, or a phone prefix
- Does not resolve legacy three-letter abbreviations — CST, IST, and EST are ambiguous and are rejected
- Does not read the system clock; there is no 'now' in this skill
- Does not convert a duration or a recurring series (use time.generate_recurrence)
- Does not format for display in a locale (the output is ISO-8601)
- Guessing a zone from free text such as 'Pacific Time'
- Converting a date without a time (there is nothing to convert)
- Formatting a timestamp for a locale-specific display string
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "time.convert_timezone",
"input": {
"dateTime": "2026-03-15T14:30:00",
"toZone": "America/New_York",
"fromZone": "Europe/Brussels"
}
}Examples
Convert a plain local time between two zones
{
"dateTime": "2026-03-15T14:30:00",
"toZone": "America/New_York",
"fromZone": "Europe/Brussels"
}{
"transition": {
"resolvedBy": "none",
"kind": "NONE"
},
"epochMillis": 1773581400000,
"_meta": {
"tzdbVersion": "2026b"
},
"source": {
"dateTime": "2026-03-15T14:30:00+01:00",
"zone": "Europe/Brussels",
"offset": "+01:00"
},
"target": {
"dateTime": "2026-03-15T09:30:00-04:00",
"zone": "America/New_York",
"offset": "-04:00"
}
}Resolve a clock-change overlap explicitly
{
"fromZone": "Europe/Brussels",
"toZone": "UTC",
"ambiguityPolicy": "later",
"dateTime": "2026-10-25T02:30:00"
}{
"transition": {
"resolvedBy": "later",
"kind": "OVERLAP"
},
"epochMillis": 1792891800000,
"_meta": {
"tzdbVersion": "2026b"
},
"source": {
"dateTime": "2026-10-25T02:30:00+01:00",
"zone": "Europe/Brussels",
"offset": "+01:00"
},
"target": {
"dateTime": "2026-10-25T01:30:00Z",
"zone": "UTC",
"offset": "Z"
}
}Recommended use cases
- Convert a stored UTC timestamp into a user's local zone for a notification
- Move a meeting time between two offices and see which side crosses a DST change
- Decide explicitly what a 02:30 reading means on a clock-change night
Avoid for
- Guessing a zone from free text such as 'Pacific Time'
- Converting a date without a time (there is nothing to convert)
- Formatting a timestamp for a locale-specific display string
Related skills
Composable with
Safety & privacy
- Runs without calling any external service.
- Your payloads are never stored permanently.
- Telemetry captures metadata only — never your payload contents.
- We never train models on your payloads.
- No human reviews your payloads.