TypeScript Unix Timestamp Guide
A comprehensive guide to working with Unix timestamps in TypeScript. Learn how to get the current timestamp, convert between timestamps and Date objects, format dates, and leverage TypeScript's type system for safer time handling.
Quick Reference
Get Current Timestamp
Date.now()Timestamp to Date
new Date(timestamp * 1000)Date to Timestamp
Math.floor(date.getTime() / 1000)Type-Safe Timestamp
type Timestamp = numberType-Safe Timestamp Handling
Create type-safe timestamp utilities in TypeScript:
// Create branded types for timestamps
type UnixTimestamp = number & { readonly __brand: 'UnixTimestamp' }
type MillisecondTimestamp = number & { readonly __brand: 'MillisecondTimestamp' }
// Type guards
function isUnixTimestamp(value: number): value is UnixTimestamp {
return value > 0 && value < 4102444800 // Between 1970 and 2100
}
function isMillisecondTimestamp(value: number): value is MillisecondTimestamp {
return value > 0 && value < 4102444800000
}
// Conversion functions
function toUnixTimestamp(ms: MillisecondTimestamp): UnixTimestamp {
return Math.floor(ms / 1000) as UnixTimestamp
}
function toMillisecondTimestamp(unix: UnixTimestamp): MillisecondTimestamp {
return (unix * 1000) as MillisecondTimestamp
}
// Usage
const now: MillisecondTimestamp = Date.now() as MillisecondTimestamp
const timestamp: UnixTimestamp = toUnixTimestamp(now)
console.log(timestamp) // Output: 1733616000Note: Branded types provide compile-time safety to prevent mixing Unix timestamps with millisecond timestamps.
Getting the Current Unix Timestamp
TypeScript provides the same Date API as JavaScript with added type safety:
// Get current timestamp in milliseconds
const timestampMs: number = Date.now()
console.log(timestampMs) // Output: 1733616000123
// Get current timestamp in seconds (Unix timestamp)
const timestamp: number = Math.floor(Date.now() / 1000)
console.log(timestamp) // Output: 1733616000
// Type-safe version
type UnixTimestamp = number
function getCurrentTimestamp(): UnixTimestamp {
return Math.floor(Date.now() / 1000)
}
const currentTime: UnixTimestamp = getCurrentTimestamp()
console.log(currentTime) // Output: 1733616000
// With validation
function getValidTimestamp(): UnixTimestamp | null {
const ts = Math.floor(Date.now() / 1000)
return ts > 0 && ts < 4102444800 ? ts : null
}Converting Timestamp to Date
Convert a Unix timestamp to a Date object with type safety:
// Basic conversion
function timestampToDate(timestamp: number): Date {
return new Date(timestamp * 1000)
}
const timestamp: number = 1733616000
const date: Date = timestampToDate(timestamp)
console.log(date) // Output: Date object
// Type-safe conversion
type UnixTimestamp = number
function safeTimestampToDate(timestamp: UnixTimestamp): Date {
if (timestamp < 0 || timestamp > 4102444800) {
throw new Error('Invalid timestamp')
}
return new Date(timestamp * 1000)
}
// With error handling
function tryTimestampToDate(timestamp: number): Date | null {
try {
const date = new Date(timestamp * 1000)
return isNaN(date.getTime()) ? null : date
} catch {
return null
}
}
// Format the date
const formatted: string = date.toISOString()
console.log(formatted) // Output: 2024-12-07T18:00:00.000Z
// Type-safe formatter
interface DateFormatter {
format(date: Date): string
}
class ISOFormatter implements DateFormatter {
format(date: Date): string {
return date.toISOString()
}
}
const formatter: DateFormatter = new ISOFormatter()
console.log(formatter.format(date))Converting Date to Timestamp
Convert a Date object or date string to a Unix timestamp with type safety:
type UnixTimestamp = number
// Current date to timestamp
function dateToTimestamp(date: Date): UnixTimestamp {
return Math.floor(date.getTime() / 1000)
}
const now: Date = new Date()
const timestamp: UnixTimestamp = dateToTimestamp(now)
console.log(timestamp) // Output: 1733616000
// String to timestamp with validation
function stringToTimestamp(dateString: string): UnixTimestamp | null {
const date = new Date(dateString)
if (isNaN(date.getTime())) {
return null
}
return Math.floor(date.getTime() / 1000)
}
const ts1 = stringToTimestamp('2024-12-07T18:00:00Z')
console.log(ts1) // Output: 1733616000
// Generic converter with type safety
interface TimestampConverter<T> {
toTimestamp(input: T): UnixTimestamp
}
class DateConverter implements TimestampConverter<Date> {
toTimestamp(date: Date): UnixTimestamp {
return Math.floor(date.getTime() / 1000)
}
}
class StringConverter implements TimestampConverter<string> {
toTimestamp(dateString: string): UnixTimestamp {
const date = new Date(dateString)
if (isNaN(date.getTime())) {
throw new Error('Invalid date string')
}
return Math.floor(date.getTime() / 1000)
}
}
const dateConverter = new DateConverter()
const stringConverter = new StringConverter()
console.log(dateConverter.toTimestamp(new Date()))
console.log(stringConverter.toTimestamp('2024-12-07'))Type-Safe Timestamp Utility Class
Create a comprehensive utility class for timestamp operations:
type UnixTimestamp = number
class TimestampUtil {
private static readonly MIN_TIMESTAMP = 0
private static readonly MAX_TIMESTAMP = 4102444800 // Year 2100
static now(): UnixTimestamp {
return Math.floor(Date.now() / 1000)
}
static fromDate(date: Date): UnixTimestamp {
return Math.floor(date.getTime() / 1000)
}
static toDate(timestamp: UnixTimestamp): Date {
this.validate(timestamp)
return new Date(timestamp * 1000)
}
static fromString(dateString: string): UnixTimestamp {
const date = new Date(dateString)
if (isNaN(date.getTime())) {
throw new Error(`Invalid date string: ${dateString}`)
}
return this.fromDate(date)
}
static validate(timestamp: number): asserts timestamp is UnixTimestamp {
if (timestamp < this.MIN_TIMESTAMP || timestamp > this.MAX_TIMESTAMP) {
throw new Error(`Invalid timestamp: ${timestamp}`)
}
}
static isValid(timestamp: number): timestamp is UnixTimestamp {
return timestamp >= this.MIN_TIMESTAMP && timestamp <= this.MAX_TIMESTAMP
}
static format(timestamp: UnixTimestamp, locale: string = 'en-US'): string {
return this.toDate(timestamp).toLocaleString(locale)
}
static add(timestamp: UnixTimestamp, seconds: number): UnixTimestamp {
return timestamp + seconds
}
static diff(ts1: UnixTimestamp, ts2: UnixTimestamp): number {
return Math.abs(ts1 - ts2)
}
}
// Usage
const now = TimestampUtil.now()
console.log(now)
const date = TimestampUtil.toDate(1733616000)
console.log(date)
const formatted = TimestampUtil.format(1733616000)
console.log(formatted)
const tomorrow = TimestampUtil.add(now, 86400)
console.log(tomorrow)Common Use Cases
API Response Type
type UnixTimestamp = number
interface ApiResponse {
id: string
createdAt: UnixTimestamp
updatedAt: UnixTimestamp
data: unknown
}
interface User {
id: string
name: string
registeredAt: UnixTimestamp
lastLogin: UnixTimestamp
}
// Type guard for API responses
function isValidApiResponse(obj: unknown): obj is ApiResponse {
const response = obj as ApiResponse
return (
typeof response.id === 'string' &&
typeof response.createdAt === 'number' &&
typeof response.updatedAt === 'number' &&
response.createdAt > 0 &&
response.updatedAt > 0
)
}
// Usage
async function fetchUser(id: string): Promise<User | null> {
const response = await fetch(`/api/users/${id}`)
const data = await response.json()
if (!isValidApiResponse(data)) {
return null
}
return {
id: data.id,
name: (data.data as { name: string }).name,
registeredAt: data.createdAt,
lastLogin: data.updatedAt,
}
}Time Range Filtering
type UnixTimestamp = number
interface TimeRange {
start: UnixTimestamp
end: UnixTimestamp
}
interface Event {
id: string
name: string
timestamp: UnixTimestamp
}
class TimeRangeFilter {
constructor(private range: TimeRange) {
if (range.start > range.end) {
throw new Error('Invalid time range: start must be before end')
}
}
isInRange(timestamp: UnixTimestamp): boolean {
return timestamp >= this.range.start && timestamp <= this.range.end
}
filter<T extends { timestamp: UnixTimestamp }>(items: T[]): T[] {
return items.filter(item => this.isInRange(item.timestamp))
}
static last24Hours(): TimeRange {
const now = Math.floor(Date.now() / 1000)
return {
start: now - 86400,
end: now,
}
}
static lastWeek(): TimeRange {
const now = Math.floor(Date.now() / 1000)
return {
start: now - 604800,
end: now,
}
}
}
// Usage
const events: Event[] = [
{ id: '1', name: 'Event 1', timestamp: 1733616000 },
{ id: '2', name: 'Event 2', timestamp: 1733619600 },
]
const filter = new TimeRangeFilter(TimeRangeFilter.last24Hours())
const recentEvents = filter.filter(events)
console.log(recentEvents)Timestamp Cache with Expiry
type UnixTimestamp = number
interface CacheEntry<T> {
value: T
expiresAt: UnixTimestamp
}
class TimestampCache<T> {
private cache = new Map<string, CacheEntry<T>>()
set(key: string, value: T, ttlSeconds: number): void {
const expiresAt = Math.floor(Date.now() / 1000) + ttlSeconds
this.cache.set(key, { value, expiresAt })
}
get(key: string): T | undefined {
const entry = this.cache.get(key)
if (!entry) return undefined
const now = Math.floor(Date.now() / 1000)
if (now >= entry.expiresAt) {
this.cache.delete(key)
return undefined
}
return entry.value
}
has(key: string): boolean {
return this.get(key) !== undefined
}
clear(): void {
this.cache.clear()
}
cleanup(): number {
const now = Math.floor(Date.now() / 1000)
let removed = 0
for (const [key, entry] of this.cache.entries()) {
if (now >= entry.expiresAt) {
this.cache.delete(key)
removed++
}
}
return removed
}
}
// Usage
const cache = new TimestampCache<string>()
cache.set('user:123', 'John Doe', 3600) // Expires in 1 hour
const value = cache.get('user:123')
console.log(value) // 'John Doe' or undefined if expiredBest Practices
Use type aliases for timestamps
Create type UnixTimestamp = number for better code documentation.
Leverage branded types for safety
Use branded types to prevent accidental mixing of Unix and millisecond timestamps.
Create type guards for validation
Use type predicates to validate timestamps at runtime with compile-time safety.
Use interfaces for timestamp-based data
Define clear interfaces for objects containing timestamps.
Prefer utility classes over loose functions
Organize timestamp operations in classes for better maintainability.
Enable strict mode
Use strict: true in tsconfig.json for maximum type safety.