JSON has no native date type. That single fact causes more bugs than you might expect. When you receive a JSON payload from an API, the timestamp could be an integer, a string, or even an object — and each format requires different handling.

This guide covers every timestamp format you will encounter in JSON, how to parse and convert them, and how to avoid the most common pitfalls when working with date-time data in JSON APIs.

How JSON Handles (or Does Not Handle) Dates

The JSON specification defines exactly six data types: string, number, object, array, boolean, and null. Notice what is missing: there is no date type.

This means every API designer has to make their own choice about how to represent dates in JSON. The three most common approaches are:

Format Example Pros Cons
Unix timestamp (integer) 1753401600 Compact, sortable, timezone-free Not human-readable
ISO 8601 string "2026-07-25T00:00:00Z" Human-readable, standard Verbose, parsing required
Custom string "07/25/2026" Familiar to end users Ambiguous, hard to parse

Most modern REST APIs use either Unix timestamps or ISO 8601 strings. GraphQL APIs tend to favor ISO 8601. Let us look at how to handle each one.

Working with Unix Timestamps in JSON

Receiving Timestamps from an API

When an API returns Unix timestamps as integers, you need to convert them to usable date objects in your code.

// Typical API response
const response = {
  "id": 1001,
  "name": "Server restart",
  "created_at": 1753401600,
  "updated_at": 1753488000,
  "scheduled_for": 1754092800
};

// Convert to JavaScript Date objects
const event = {
  ...response,
  created_at: new Date(response.created_at * 1000),
  updated_at: new Date(response.updated_at * 1000),
  scheduled_for: new Date(response.scheduled_for * 1000)
};

console.log(event.created_at.toLocaleString());
// "July 25, 2026, 12:00:00 AM"

The multiplication by 1000 is critical. JavaScript's Date constructor expects milliseconds, but Unix timestamps are in seconds. Forget this step and your dates will be stuck in January 1970.

Sending Timestamps in JSON Requests

When you need to send a timestamp back to an API, convert your date object to a Unix timestamp:

const futureDate = new Date('2026-08-01T00:00:00Z');
const timestamp = Math.floor(futureDate.getTime() / 1000);

const payload = {
  event: "Maintenance window",
  starts_at: timestamp
};

// Send with fetch
fetch('/api/events', {
  method: 'POST',
  headers: { 'Content-Type': 'application/json' },
  body: JSON.stringify(payload)
});

Python: Parsing JSON Timestamps

import json
from datetime import datetime, timezone

# JSON response from an API
json_data = '''
{
  "id": 1001,
  "created_at": 1753401600,
  "updated_at": 1753488000
}
'''

data = json.loads(json_data)

# Convert Unix timestamps to datetime objects
data['created_at'] = datetime.fromtimestamp(data['created_at'], tz=timezone.utc)
data['updated_at'] = datetime.fromtimestamp(data['updated_at'], tz=timezone.utc)

print(data['created_at'].isoformat())
# 2026-07-25T00:00:00+00:00

# Convert back to timestamp for API requests
outgoing = {
    "event": "Deploy",
    "scheduled_at": int(datetime(2026, 8, 1, tzinfo=timezone.utc).timestamp())
}
print(json.dumps(outgoing))
# {"event": "Deploy", "scheduled_at": 1754092800}

Working with ISO 8601 Strings in JSON

ISO 8601 is the international standard for date-time representation. It looks like this: 2026-07-25T00:00:00Z.

JavaScript: Parsing ISO Strings

const jsonStr = '{"event": "Deploy", "time": "2026-07-25T00:00:00Z"}';
const data = JSON.parse(jsonStr);

// JavaScript natively parses ISO 8601 strings
const date = new Date(data.time);
console.log(date.toISOString());  // "2026-07-25T00:00:00.000Z"
console.log(date.getTime());       // 1753401600000 (milliseconds)

// Convert to Unix timestamp (seconds)
const unixTs = Math.floor(date.getTime() / 1000);
console.log(unixTs);  // 1753401600

Python: Parsing ISO Strings

import json
from datetime import datetime, timezone

json_str = '{"event": "Deploy", "time": "2026-07-25T00:00:00Z"}'
data = json.loads(json_str)

# Parse ISO 8601 string (Python 3.7+)
dt = datetime.fromisoformat(data['time'].replace('Z', '+00:00'))
print(dt)  # 2026-07-25 00:00:00+00:00

# Convert to Unix timestamp
ts = int(dt.timestamp())
print(ts)  # 1753401600

Handling Mixed Timestamp Formats

Real-world APIs are messy. Sometimes the same API returns different timestamp formats in different endpoints, or even within the same response. Here is how to handle that gracefully.

JavaScript: Auto-Detect Format

function parseTimestamp(value) {
  // If it is a number, assume Unix timestamp in seconds
  if (typeof value === 'number') {
    // Heuristic: 10 digits = seconds, 13 digits = milliseconds
    if (value > 1e12) {
      return new Date(value);  // already milliseconds
    }
    return new Date(value * 1000);  // convert seconds to ms
  }

  // If it is a string, try ISO 8601 first
  if (typeof value === 'string') {
    const date = new Date(value);
    if (!isNaN(date.getTime())) {
      return date;
    }
  }

  throw new Error(`Cannot parse timestamp: ${value}`);
}

// Works with all common formats
console.log(parseTimestamp(1753401600));              // Unix seconds
console.log(parseTimestamp(1753401600000));           // Unix milliseconds
console.log(parseTimestamp("2026-07-25T00:00:00Z"));  // ISO 8601

Python: Auto-Detect Format

from datetime import datetime, timezone

def parse_timestamp(value):
    if isinstance(value, (int, float)):
        # Heuristic: > 1e12 means milliseconds
        if value > 1e12:
            return datetime.fromtimestamp(value / 1000, tz=timezone.utc)
        return datetime.fromtimestamp(value, tz=timezone.utc)

    if isinstance(value, str):
        # Try ISO 8601
        try:
            return datetime.fromisoformat(value.replace('Z', '+00:00'))
        except ValueError:
            pass

    raise ValueError(f"Cannot parse timestamp: {value}")

# Works with all common formats
print(parse_timestamp(1753401600))              # Unix seconds
print(parse_timestamp(1753401600000))           # Unix milliseconds
print(parse_timestamp("2026-07-25T00:00:00Z"))  # ISO 8601

Timestamps in JSON Schema and Validation

When you define a JSON Schema for your API, you can specify the expected timestamp format:

{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "type": "object",
  "properties": {
    "created_at": {
      "type": "integer",
      "description": "Unix timestamp in seconds",
      "minimum": 0,
      "maximum": 2147483647
    },
    "updated_at": {
      "type": "string",
      "format": "date-time",
      "description": "ISO 8601 date-time string"
    }
  },
  "required": ["created_at"]
}

The "format": "date-time" constraint tells validators to expect an ISO 8601 string. For Unix timestamps, use "type": "integer" with reasonable min/max bounds.

Converting JSON Timestamps for Display

Once you have parsed a timestamp from JSON, you usually need to format it for display. Here are common patterns.

JavaScript: Formatting for Users

function formatTimestamp(ts, locale = 'en-US') {
  const date = new Date(ts * 1000);

  return {
    // Full date and time
    long: date.toLocaleString(locale, {
      year: 'numeric',
      month: 'long',
      day: 'numeric',
      hour: '2-digit',
      minute: '2-digit'
    }),

    // Short date only
    short: date.toLocaleDateString(locale),

    // Relative time ("2 hours ago")
    relative: getRelativeTime(date)
  };
}

function getRelativeTime(date) {
  const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
  const intervals = [
    { label: 'year', seconds: 31536000 },
    { label: 'month', seconds: 2592000 },
    { label: 'week', seconds: 604800 },
    { label: 'day', seconds: 86400 },
    { label: 'hour', seconds: 3600 },
    { label: 'minute', seconds: 60 }
  ];

  for (const interval of intervals) {
    const count = Math.floor(seconds / interval.seconds);
    if (count >= 1) {
      return `${count} ${interval.label}${count > 1 ? 's' : ''} ago`;
    }
  }
  return 'just now';
}

// Usage
const result = formatTimestamp(1753401600);
console.log(result.long);     // "July 25, 2026, 12:00 AM"
console.log(result.short);    // "7/25/2026"
console.log(result.relative); // "X days ago"

FAQ

What is the best timestamp format for JSON APIs?

There is no single "best" format. Unix timestamps (integers) are compact and easy to compare, making them ideal for internal APIs and database storage. ISO 8601 strings are human-readable and self-documenting, making them better for public APIs and developer-facing documentation. Choose based on your audience.

How do I handle timezone information in JSON timestamps?

Unix timestamps are inherently timezone-free (they always represent UTC). ISO 8601 strings can include timezone offsets (+05:30) or use Z for UTC. The safest approach: store and transmit everything in UTC, convert to local time only in the UI layer.

Why does my JSON timestamp show the wrong date?

The most common cause is the seconds vs milliseconds confusion. If your timestamp has 10 digits, it is in seconds. If it has 13 digits, it is in milliseconds. Passing a seconds value to a function expecting milliseconds (or vice versa) will produce wildly incorrect dates.

Can I store dates directly in JSON?

No. JSON has no date type. You must use either a number (Unix timestamp) or a string (ISO 8601 or custom format). This is by design — the JSON specification intentionally keeps the type system minimal.

How do I validate timestamp formats in JSON?

Use JSON Schema validation. For ISO 8601 strings, use "format": "date-time". For Unix timestamps, use "type": "integer" with minimum and maximum constraints. Libraries like Ajv (JavaScript) and jsonschema (Python) can enforce these rules automatically.

Conclusion

JSON has no native date type, which means every developer must handle timestamp conversion manually. The two dominant formats — Unix timestamps (integers) and ISO 8601 strings — each have their strengths and trade-offs.

Key takeaways:

  • Always check whether a JSON timestamp is in seconds (10 digits) or milliseconds (13 digits) before converting
  • ISO 8601 strings are human-readable but require parsing; Unix timestamps are compact but opaque
  • Store and transmit timestamps in UTC; convert to local time only at the display layer
  • Use auto-detection functions to handle APIs that mix timestamp formats

When you need to quickly inspect or convert timestamp values in JSON data, the FastUnix JSON Formatter can help you validate and beautify JSON payloads, while the FastUnix Timestamp Converter provides instant conversion between Unix timestamps and human-readable dates. For encoding timestamps in URL parameters, the URL Encoder handles special characters correctly.