Date-Time Parser
time.parse_datetime
Overview
Parses a date/time string against an ordered list of candidate formats — named java.time formatters or explicit patterns — and returns a normalized ISO-8601 value, the format that matched, and the precision the input actually carried (YEAR through NANO). Parsing is strict by default: 2026-02-30 is rejected rather than rolled to March. Text that no candidate matches returns parsed: false with a finding, not an error. There is no natural-language parsing and no 'now': a zone-less input stays local unless 'defaultZone' supplies one.
Date strings from upstream systems vary in format — we parse against your candidate ladder and tell you what matched and how precise the input was.
Reliability
Same text, same formats, same answer — nothing here reads a clock, so no part of the result is relative to now, and it is reproducible for a given IANA time-zone database version, reported as _meta.tzdbVersion. Candidate order is part of the contract: the first format that matches wins, so put your most specific format first. Under strict resolution a pattern's y is read as the proleptic year u unless the pattern also declares an era, which is why yyyy-MM-dd behaves the way you would expect. Text that no candidate matches is an ordinary success with parsed false and a DATETIME_UNPARSEABLE finding, so branch on parsed rather than on your error path. Only two conditions stop us evaluating at all. DATETIME_FORMAT_INVALID — trigger: something in your request is not a usable format instruction — an entry in formats that is neither a known formatter name nor a valid java.time pattern, or a locale that is not a BCP 47 language tag; retryable: no, the same request always fails; next: check the name against the supported list above (they are case-sensitive), check unquoted letters in your pattern, and write the locale as en-US or fr. This is about the format you sent, never about the text you asked us to parse. TIMEZONE_UNKNOWN — trigger: defaultZone is not a zone we can resolve, which covers a typo, a three-letter abbreviation such as CST or EST, and a fixed offset such as +02:00; retryable: no; next: send a region-based identifier like Europe/Brussels, or UTC, or leave the field out and accept a local reading.
Context footprint
One call replaces a format-guessing loop and returns a handful of scalar fields instead of a parsed object graph. A successful call costs 1 execution credit.
When to use it
When a date-time arrives as text and you need it normalized with explicit format and precision reporting.
Do not use for relative phrases like "next Tuesday", when you already hold a normalized instant, or for zone conversion (use time.convert_timezone).
Scope
Non-goals
- Does not parse natural language such as 'next Tuesday' or 'in three days'
- Does not read the system clock, so nothing is relative to 'now'
- Does not guess a zone the input does not carry and the caller does not supply
- Does not roll an impossible date — 2026-02-30 is rejected, not moved to March
- Does not invent a time for a date-only input, and so returns no epochMillis for one
Properties
Capabilities
Cost & billing
Flat rate per invocation
File handling
How we handle your data
What this means
This skill may receive sensitive content and may return submitted, transformed, extracted, or reformatted content.
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 may contain submitted or transformed 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 |
|---|---|---|---|
| text | string | Yes | Date-time text to parse. |
| formats | array | No | Ordered candidate formats; omit or empty for the pinned ladder. |
| defaultZone | string | No | Optional IANA default zone. |
| locale | string | No | BCP 47 parsing locale; omit it for the engine default locale. |
| strict | boolean | No | Whether impossible values are rejected; omit it for true. |
Output schema
| Field | Type | Required | Description |
|---|---|---|---|
| parsed | boolean | Yes | Whether one candidate matched. |
| iso | string | No | Normalized ISO-8601 value. |
| epochMillis | integer | No | Resolved Unix epoch milliseconds. |
| zone | string | No | Resolved IANA zone or UTC offset. |
| zoneKnown | boolean | No | Whether the value resolved to a zone. |
| matchedFormat | string | No | Exact successful candidate format. |
| precision | string | No | Precision carried by the input. |
| findings | array | Yes | From 0 through 2 bounded parser findings, each a closed code, message, path, and severity. |
| _meta | object | No | Closed parser-version and candidate-count receipt with tzdbVersion and how many formats were tried. |
API contract
POST /v1/executecurl -sS -X POST "$BASE/v1/execute" -H "Authorization: Bearer $KEY" -H 'Content-Type: application/json' -d '{"skillKey":"time.parse_datetime","input":{"text":"2026-03-15 14:30:00","defaultZone":"Europe/Brussels"}}'import { Squillify } from "@squillify/sdk";
const sq = new Squillify({ apiKey: process.env.SQUILLIFY_API_KEY });
const { output } = await sq.execute("time.parse_datetime", {"defaultZone":"Europe/Brussels","text":"2026-03-15 14:30:00"});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. |
| DATETIME_FORMAT_INVALID | 400 | No | The request payload failed this skill's input validation. |
| TIMEZONE_UNKNOWN | 400 | No | The request payload failed this skill's input validation. |
Other limits
| Limit | Value |
|---|---|
| Recommended inline bytes | 32 KiB |
Limitations
- Does not parse natural language such as 'next Tuesday' or 'in three days'
- Does not read the system clock, so nothing is relative to 'now'
- Does not guess a zone the input does not carry and the caller does not supply
- Does not roll an impossible date — 2026-02-30 is rejected, not moved to March
- Does not invent a time for a date-only input, and so returns no epochMillis for one
- Interpreting relative phrases such as 'yesterday'
- Converting between zones once parsed (use time.convert_timezone)
- Formatting a value for display
How to call
POST /v1/execute (requires authentication)
{
"skillKey": "time.parse_datetime",
"input": {
"defaultZone": "Europe/Brussels",
"text": "2026-03-15 14:30:00"
}
}Examples
Parse a common space-separated timestamp in a zone
{
"defaultZone": "Europe/Brussels",
"text": "2026-03-15 14:30:00"
}{
"epochMillis": 1773581400000,
"zoneKnown": true,
"matchedFormat": "uuuu-MM-dd HH:mm:ss",
"findings": [],
"precision": "SECOND",
"parsed": true,
"zone": "Europe/Brussels",
"iso": "2026-03-15T14:30:00+01:00",
"_meta": {
"candidatesTried": 7,
"tzdbVersion": "2026b"
}
}A date-only input keeps day precision
{
"text": "2026-03-15"
}{
"parsed": true,
"matchedFormat": "ISO_LOCAL_DATE",
"findings": [],
"_meta": {
"candidatesTried": 5,
"tzdbVersion": "2026b"
},
"precision": "DAY",
"iso": "2026-03-15",
"zoneKnown": false
}Recommended use cases
- Normalize timestamps arriving from several upstream systems in different formats
- Decide whether a user-supplied date string is well formed before storing it
- Learn whether an input carried a date, a minute, or a nanosecond
Avoid for
- Interpreting relative phrases such as 'yesterday'
- Converting between zones once parsed (use time.convert_timezone)
- Formatting a value for display
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.