Convert Unix Timestamp in Bash/Shell

Converting Unix timestamps in Bash/Shell is primarily done using the date command. The main challenge is the difference between GNU date (Linux) and BSD date (macOS) syntax.

Get Current Unix Timestamp

All Systems
# Current timestamp in seconds
date +%s
# Example output: 1704067200

# Current timestamp in milliseconds (GNU/Linux only)
date +%s%3N
# Example output: 1704067200123

Unix Timestamp to Date

GNU/Linux
# Convert timestamp to readable date
date -d @1704067200
# Mon Jan  1 00:00:00 UTC 2024

# Convert with specific format
date -d @1704067200 +"%Y-%m-%d %H:%M:%S"
# 2024-01-01 00:00:00

# Convert to UTC
date -d @1704067200 -u
# Mon Jan  1 00:00:00 UTC 2024
BSD/macOS
# Convert timestamp to readable date
date -r 1704067200
# Mon Jan  1 00:00:00 UTC 2024

# Convert with specific format
date -r 1704067200 +"%Y-%m-%d %H:%M:%S"
# 2024-01-01 00:00:00

# Convert to UTC
date -r 1704067200 -u
# Mon Jan  1 00:00:00 UTC 2024

Date to Unix Timestamp

GNU/Linux
# Convert specific date to timestamp
date -d "2024-01-01 00:00:00" +%s
# 1704067200

# Convert relative date to timestamp
date -d "yesterday" +%s
date -d "next monday" +%s
date -d "2 weeks ago" +%s
BSD/macOS
# Convert specific date to timestamp
date -j -f "%Y-%m-%d %H:%M:%S" "2024-01-01 00:00:00" +%s
# 1704067200

# Note: BSD date has limited relative date support
# For relative dates, use -v flag
date -j -v-1d +%s  # yesterday
date -j -v+1w +%s  # next week

Cross-Platform Compatibility

Portable Script
#!/bin/bash

# Detect date command type
if date --version >/dev/null 2>&1; then
    # GNU date
    timestamp_to_date() {
        date -d "@$1" +"%Y-%m-%d %H:%M:%S"
    }
else
    # BSD date
    timestamp_to_date() {
        date -r "$1" +"%Y-%m-%d %H:%M:%S"
    }
fi

# Usage
timestamp_to_date 1704067200
# 2024-01-01 00:00:00

One-Liners with awk/perl

awk
# Convert timestamp using awk (built-in strftime)
echo "1704067200" | awk '{print strftime("%Y-%m-%d %H:%M:%S", $1)}'
# 2024-01-01 00:00:00

# Process file with timestamps
awk '{print $1, strftime("%Y-%m-%d %H:%M:%S", $2)}' file.txt
perl
# Convert timestamp using perl
perl -e 'print scalar localtime(1704067200), "
"'
# Mon Jan  1 00:00:00 2024

# With custom format
perl -e 'use POSIX qw(strftime); print strftime("%Y-%m-%d %H:%M:%S", localtime(1704067200)), "
"'
# 2024-01-01 00:00:00
python
# Convert timestamp using python
python3 -c 'import datetime; print(datetime.datetime.fromtimestamp(1704067200))'
# 2024-01-01 00:00:00

# With custom format
python3 -c 'import datetime; print(datetime.datetime.fromtimestamp(1704067200).strftime("%Y-%m-%d %H:%M:%S"))'
# 2024-01-01 00:00:00

Timezone Handling

GNU/Linux
# Convert to specific timezone
TZ="America/New_York" date -d @1704067200
# Sun Dec 31 19:00:00 EST 2023

# UTC time
date -d @1704067200 -u
# Mon Jan  1 00:00:00 UTC 2024

# Local time
date -d @1704067200
# Mon Jan  1 00:00:00 <local timezone> 2024
BSD/macOS
# Convert to specific timezone
TZ="America/New_York" date -r 1704067200
# Sun Dec 31 19:00:00 EST 2023

# UTC time
date -r 1704067200 -u
# Mon Jan  1 00:00:00 UTC 2024

# Local time
date -r 1704067200
# Mon Jan  1 00:00:00 <local timezone> 2024

Common Pitfalls

GNU vs BSD Syntax

The most common issue is using GNU date syntax on macOS or vice versa. Always check which version you have.

# ❌ Wrong on macOS
date -d @1704067200
# date: illegal option -- d

# ✅ Correct on macOS
date -r 1704067200

# ❌ Wrong on Linux (tries to read file modification time)
date -r 1704067200
# date: 1704067200: No such file or directory

# ✅ Correct on Linux
date -d @1704067200

Timezone Assumptions

Date commands use the system timezone by default. Always specify timezone if you need consistent results across systems.

# ❌ Ambiguous - depends on system timezone
date -d @1704067200

# ✅ Explicit UTC
date -d @1704067200 -u

# ✅ Explicit timezone
TZ="UTC" date -d @1704067200

Millisecond Precision

Not all systems support millisecond precision. %N (nanoseconds) is GNU-specific and not available on BSD/macOS.

# ❌ Doesn't work on macOS
date +%s%3N

# ✅ Works on Linux/GNU
date +%s%3N

# ✅ Cross-platform alternative for milliseconds
python3 -c 'import time; print(int(time.time() * 1000))'

Advanced Examples

Batch Processing (GNU/Linux)
# Process multiple timestamps from file
while read -r timestamp; do
    echo "$timestamp -> $(date -d "@$timestamp" +"%Y-%m-%d %H:%M:%S")"
done < timestamps.txt

# Convert log timestamps
awk '{print $1, strftime("%Y-%m-%d %H:%M:%S", $2)}' /var/log/syslog
Batch Processing (BSD/macOS)
# Process multiple timestamps from file
while read -r timestamp; do
    echo "$timestamp -> $(date -r "$timestamp" +"%Y-%m-%d %H:%M:%S")"
done < timestamps.txt

# Convert log timestamps (awk works the same)
awk '{print $1, strftime("%Y-%m-%d %H:%M:%S", $2)}' /var/log/system.log
Real-time Monitoring (GNU/Linux)
# Show current timestamp and date every second
while true; do
    ts=$(date +%s)
    echo "$ts -> $(date -d "@$ts")"
    sleep 1
done

# Monitor file changes with timestamps (inotifywait is Linux-specific)
inotifywait -m /path/to/file | while read path; do
    echo "$(date +%s): $path"
done
Real-time Monitoring (BSD/macOS)
# Show current timestamp and date every second
while true; do
    ts=$(date +%s)
    echo "$ts -> $(date -r "$ts")"
    sleep 1
done

# Monitor file changes with timestamps (use fswatch on macOS)
fswatch /path/to/file | while read path; do
    echo "$(date +%s): $path"
done

Frequently Asked Questions

What is the difference between GNU and BSD date commands?

GNU date (Linux) uses -d for date strings and @ for timestamps, while BSD date (macOS) uses -r for timestamps and -f for input formats. The syntax for getting current timestamp is the same.

Why does my date command fail on macOS?

macOS uses BSD date, not GNU date. Use date -r timestamp instead of date -d @timestamp (note: BSD does not use the @ prefix). For complex date parsing, you may need to use -f with format strings.

How do I handle milliseconds in shell?

Standard Unix timestamps are in seconds. For milliseconds, divide by 1000 before converting to date, or multiply by 1000 when getting current time with date +%s%3N (GNU only).

Can I convert timestamps without the date command?

Yes, you can use awk, perl, or python one-liners. These are useful when date command is unavailable or when you need more control over formatting.