Milliseconds vs Seconds Timestamps: When to Use Each
One of the most common sources of timestamp bugs in software development is the confusion between second-precision and millisecond-precision Unix timestamps. The two formats represent the same concept — time elapsed since the Unix epoch — but differ by a factor of 1000. Mixing them silently produces dates that are either 1000 seconds too far in the future or 1000 times too far, sometimes landing in the year 50,000. Knowing when to use each precision prevents a whole class of bugs.
The Core Difference: What Each Format Represents
A second-precision Unix timestamp counts the number of whole seconds since January 1, 1970 at 00:00:00 UTC. As of May 2026, this value is approximately 1,747,000,000. It is a 10-digit integer. A millisecond-precision Unix timestamp counts the number of milliseconds since the same epoch. It is exactly 1000 times larger: approximately 1,747,000,000,000 as of May 2026. It is a 13-digit integer. Both formats represent the same set of instants in time. A second-precision timestamp can only represent whole seconds. A millisecond-precision timestamp can represent any point in time with up to 1-millisecond resolution. Milliseconds are sometimes further subdivided: microseconds (6 decimal places after the epoch integer) and nanoseconds (9 decimal places) exist in some systems but are rare in general web development. A quick identification heuristic: count the digits. - 10 digits (e.g., 1715500800): epoch seconds — current dates fall here. - 13 digits (e.g., 1715500800000): epoch milliseconds — JavaScript's Date.now() produces this. - Values with fewer digits may be historical dates or truncated values. - Values with more digits may be microseconds (16 digits) or nanoseconds (19 digits). Our Unix Timestamp Converter automatically detects the unit based on the digit count and displays the result correctly without requiring you to specify the unit manually.
Which Languages and Systems Use Which Unit by Default
Different languages and platforms have different default units for timestamps, and knowing these defaults is half the battle. Milliseconds by default: - JavaScript: Date.now(), new Date().getTime(), performance.now() (but relative, not epoch-based) - Java: System.currentTimeMillis(), Instant.toEpochMilli() - C#: DateTimeOffset.ToUnixTimeMilliseconds() - Redis: PEXPIREAT, PTTL, and related millisecond-precision commands Seconds by default: - Python: time.time() (returns a float where the integer part is seconds) - Unix shell: date +%s - PHP: time() - Go: time.Now().Unix() - C/C++: time(NULL) - MySQL UNIX_TIMESTAMP() function - Most Unix system calls Mixed: - PostgreSQL: EXTRACT(EPOCH FROM NOW()) returns seconds as a float; TO_TIMESTAMP() accepts seconds - Ruby: Time.now.to_i gives seconds, Time.now.to_f gives seconds with sub-second as decimal This table explains why the seconds/milliseconds mismatch is so prevalent in full-stack applications: the frontend (JavaScript) defaults to milliseconds while the backend (Python, PHP, Ruby, Go) defaults to seconds. API responses from the backend are typically in seconds, but JavaScript consumers expect milliseconds. Always multiply seconds by 1000 in JavaScript before creating a Date object.
When to Choose Milliseconds Over Seconds
Millisecond precision is the right choice when sub-second events need to be ordered or measured. Here are the key scenarios. Event ordering in distributed systems: In a high-traffic system, multiple events can happen within the same second. If you use second-precision timestamps, events that occurred in the same second cannot be ordered relative to each other. Millisecond timestamps resolve ties in most cases. For even higher-frequency systems, microseconds or sequence numbers may be needed. Performance measurement: Measuring API response time, database query duration, or code execution time requires millisecond precision at minimum. second-precision metrics are useless for performance work. Log the start timestamp and end timestamp in milliseconds, subtract to get duration in milliseconds. Browser and frontend logging: JavaScript applications should use millisecond timestamps because Date.now() is the native API and converting to seconds and back adds unnecessary complexity. Real-time applications: Chat systems, collaborative editing, and gaming backends where event ordering matters at sub-second precision should use milliseconds. JavaScript-native APIs: If your API is primarily consumed by JavaScript clients, returning millisecond timestamps aligns with Date.now() and avoids the *1000 conversion on the client side. When seconds are sufficient: for scheduling tasks (cron jobs, reminders, expiry times), logging user actions where a 1-second granularity is meaningful, database indices on date columns, and any system where the difference between two events is measured in minutes or hours rather than milliseconds. Seconds use less storage and are simpler to work with in environments that default to them.
Detecting and Fixing Unit Mismatches in Existing Systems
If you inherit a codebase or integrate with an API where the timestamp unit is undocumented or inconsistent, here is how to identify and fix the problem. Detection step 1: Check the magnitude. A seconds timestamp for any date in 2026 is between 1,700,000,000 and 1,800,000,000. A millisecond timestamp for 2026 is between 1,700,000,000,000 and 1,800,000,000,000. Any 10-digit value in the 1.7 billion range is seconds. Any 13-digit value in the 1.7 trillion range is milliseconds. Values outside these ranges are either historical, future, or wrong units. Detection step 2: Convert a known sample. Find a record in your database or API response where you know the actual date. Paste the timestamp into our converter (try both seconds and milliseconds interpretations) and see which one matches your known date. Detection step 3: Look at the code path. Find where the timestamp is set. In JavaScript, if it is Date.now() it is milliseconds. In Python, if it is int(time.time()) it is seconds, if it is int(time.time() * 1000) it is milliseconds. Fixing a mismatch in an existing database: Write a migration that detects values in the wrong range and divides or multiplies accordingly. For example, UPDATE events SET ts = ts / 1000 WHERE ts > 1000000000000 (convert any millisecond values in a seconds column to seconds). After migration, add a CHECK constraint: CHECK (ts BETWEEN 0 AND 9999999999) to enforce the seconds range for future inserts.
Frequently Asked Questions
- How do I quickly tell if a timestamp is in seconds or milliseconds?
- Count the digits. In 2026, second-precision timestamps have 10 digits (around 1.74 billion) and millisecond-precision timestamps have 13 digits (around 1.74 trillion). You can also use our Unix Timestamp Converter — paste the number in and try both interpretations. If one gives a date in 2026 and the other gives a date in 1970 or 56,000 AD, you have your answer.
- Does using milliseconds instead of seconds affect database performance?
- Negligibly for most applications. Both are stored as integers (BIGINT). Integer comparisons and index lookups are equally fast for 10-digit and 13-digit values. The only cost is the extra 3 digits of storage, which on a BIGINT (8 bytes) is nothing — the type uses 8 bytes regardless of whether the value is 1 billion or 1 trillion. Choose based on the precision you need, not on performance concerns.
- What happens if I accidentally store milliseconds in a column that expects seconds?
- The timestamp will appear to be approximately 1000 times further in the future than intended. A record created on May 12, 2026 would appear to have been created around the year 56,367. To fix existing data: UPDATE your_table SET ts = ts / 1000 WHERE ts > 9999999999 (adjust the threshold for your date range). Add validation to prevent it from happening again: reject inserts with timestamps outside the expected seconds range.