Unix Hex Timestamp Converter — Hex/Decimal Seconds or Milliseconds ↔ Date

Convert Unix timestamps in hex (0x…) or decimal to human-readable dates—and back. Auto-detects seconds vs milliseconds, shows UTC & your selected time zone. Private by design.

Display & Quick Actions

Results always include UTC; this controls the extra local view.

Override if your source is known to be seconds or ms.

Shortcut: Ctrl/Cmd + L copies share URL.

1) Hex / Decimal Unix Timestamp → Date

Hex with/without 0x is accepted. You can also use separators like 1_735_689_600 or 1 735 689 600.

Input interpreted as: —

No network processing of your timestamp/date data. Everything runs in your browser.

2) Date → Unix Timestamp (Hex & Decimal)

Interpreted in your current local time zone.

If an offset is provided, it will be respected.

Parse preview: —

Compare Two Timestamps

Delta output appears here.

Batch Convert

Batch results appear here.

Recent History

Stored locally in your browser (last 10 conversions).

    About Unix Hex Timestamps

    Release Updates

    v1.1 (February 7, 2026)

    • Added inline validation hints, interpretation badges, and date parse preview.
    • Added quick date actions (Now UTC/Local, +1h, +1d, Start of day), time zone favorites, and quick UTC/Local/Last toggles.
    • Added compare mode, batch conversion, local recent history, richer output formats, and stronger out-of-range guidance.

    Unix timestamps are everywhere, from server logs to API responses, but they are not always shown in plain decimal. Many systems store or display these values in hexadecimal, which can be confusing if you are trying to read a date quickly. This Unix Hex Timestamp converter makes the process simple by translating between hexadecimal and decimal timestamps and showing the corresponding human-readable date and time.

    A Unix timestamp is the number of seconds or milliseconds since 1970-01-01 00:00:00 UTC, also called the Unix epoch. Hexadecimal timestamps are the same numbers, just written in base 16. This tool accepts hex values with or without a 0x prefix, as well as normal decimal values. It can also detect whether the input is in seconds or milliseconds based on its size, so you do not need to guess.

    How to use it step by step

    1. Paste a timestamp in hexadecimal or decimal form.
    2. Select whether the input is seconds or milliseconds, or leave auto-detect enabled.
    3. Click Convert to see the readable date and the alternate numeric formats.
    4. Copy the result for debugging, reporting, or documentation.

    This is especially useful when you are debugging logs, reading database records, or translating timestamps from system tools that output hex values. For example, a log entry might show a hex timestamp like 0x65F21D80, and you want to know the exact time it represents. The converter gives you that answer instantly and shows the decimal value alongside it.

    Negative timestamps are supported for dates before 1970, which is helpful when working with historical records. The calculator uses precise integer math to avoid rounding errors, then displays the result with millisecond precision so it is easy to compare across systems. If the date looks off by hours, remember that timestamps are always UTC; your local time zone is only applied when the result is displayed.

    Advertisement

    Unix Hex Timestamp: Code Snippets & How-To

    A Unix timestamp represents seconds (or milliseconds) since 1970-01-01T00:00:00Z. Many logs use hexadecimal (with or without a 0x prefix). These examples show how to parse hex/decimal, auto-detect seconds vs milliseconds, and convert to human-readable dates.

    Rule of thumb

    • If the absolute value is ≳ 1e11, it’s likely milliseconds; otherwise seconds.
    • Negative values (before 1970) are valid; floor division is required when deriving seconds from ms.
    JavaScript (Browser/Node)
    function parseBigIntFlexible(s) {
      s = s.trim();
      if (/^-?0x[0-9a-f]+$/i.test(s)) return BigInt(s);
      if (/^-?[0-9a-f]+$/i.test(s) && /[a-f]/i.test(s)) return BigInt('0x'+s.replace(/^-/,''));
      if (/^-?\d+$/.test(s)) return BigInt(s);
      throw new Error('Invalid hex/decimal integer');
    }
    function unitAuto(bi) {
      const abs = bi < 0n ? -bi : bi;
      return abs >= 100_000_000_000n ? 'ms' : 's';
    }
    function floorDiv(a, b) { // floor for negatives
      const q = a / b, r = a % b;
      return (r === 0n || (a >= 0n) === (b >= 0n)) ? q : q - 1n;
    }
    // Hex/dec → Date
    function hexUnixToDate(s, unit = 'auto') {
      let bi = parseBigIntFlexible(s);
      if (unit === 'auto') unit = unitAuto(bi);
      const ms = unit === 's' ? bi * 1000n : bi;
      const max = 8_640_000_000_000_000n;
      const clamped = ms > max ? max : (ms < -max ? -max : ms);
      return new Date(Number(clamped));
    }
    // Date → hex/dec (seconds & milliseconds)
    function dateToUnixHex(date = new Date()) {
      const ms = BigInt(date.getTime());
      const sec = floorDiv(ms, 1000n);
      return {
        seconds_dec: sec.toString(),
        seconds_hex: '0x'+sec.toString(16).toUpperCase(),
        millis_dec: ms.toString(),
        millis_hex: '0x'+ms.toString(16).toUpperCase()
      };
    }
    Python 3
    import datetime, math, re
    
    HEX_RE = re.compile(r'^-?(0x)?[0-9a-f]+$', re.IGNORECASE)
    
    def parse_int_flexible(s: str) -> int:
        s = s.strip()
        if not s:
            raise ValueError("empty input")
        if s.lower().startswith('-0x'):
            return -int(s[3:], 16)
        if s.lower().startswith('0x'):
            return int(s, 16)
        if HEX_RE.match(s) and any(c.isalpha() for c in s):
            return int(s, 16) if not s.startswith('-') else -int(s[1:], 16)
        return int(s, 10)
    
    def unit_auto(v: int) -> str:
        return 'ms' if abs(v) >= 100_000_000_000 else 's'
    
    def hex_unix_to_datetime(s: str, unit: str = 'auto') -> datetime.datetime:
        v = parse_int_flexible(s)
        if unit == 'auto':
            unit = unit_auto(v)
        ms = v if unit == 'ms' else v * 1000
        # timezone-aware UTC datetime
        return datetime.datetime.fromtimestamp(ms / 1000, tz=datetime.timezone.utc)
    
    def datetime_to_unix(dt: datetime.datetime = None):
        if dt is None:
            dt = datetime.datetime.now(datetime.timezone.utc)
        if dt.tzinfo is None:
            dt = dt.astimezone()  # local -> aware
        ms = int(dt.timestamp() * 1000)
        sec = math.floor(ms / 1000)  # floor for negatives
        return {
            'seconds_dec': str(sec),
            'seconds_hex': hex(sec),
            'millis_dec': str(ms),
            'millis_hex': hex(ms)
        }
    C (portable)
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <time.h>
    #include <inttypes.h>
    
    static int is_hexlike(const char *s){
      if (!s || !*s) return 0;
      if (s[0]=='-' && s[1]) s++;
      if (s[0]=='0' && (s[1]=='x' || s[1]=='X')) return 1;
      for (const char *p=s; *p; ++p) if ((*p>='a' && *p<='f') || (*p>='A' && *p<='F')) return 1;
      return 0;
    }
    
    int main(int argc, char **argv){
      if (argc < 2){ fprintf(stderr, "usage: %s <hex|dec> [s|ms]\n", argv[0]); return 1; }
      const char *in = argv[1];
      const char *unit = (argc >= 3) ? argv[2] : "auto";
    
      int isneg = (in[0]=='-');
      if (isneg && in[1]=='0' && (in[2]=='x' || in[2]=='X')) in += 3;
      char *end = NULL;
      int base = is_hexlike(in) ? 16 : 10;
      long long sign = isneg ? -1 : 1;
      unsigned long long mag = strtoull(isneg ? in+1 : in, &end, base);
      long long val = (long long)(sign * (long long)mag);
    
      const char *mode = unit;
      if (strcmp(mode,"auto")==0){
        mode = ( llabs(val) >= 100000000000LL ) ? "ms" : "s";
      }
      long long ms = (strcmp(mode,"s")==0) ? val * 1000LL : val;
    
      time_t secs = (time_t)(ms/1000LL - ((ms<0 && ms%1000LL)!=0)); // floor for negatives
      struct tm tm_utc;
      gmtime_r(&secs, &tm_utc);
      char buf[64];
      strftime(buf, sizeof(buf), "%Y-%m-%dT%H:%M:%SZ", &tm_utc);
      printf("UTC ISO8601: %s\n", buf);
      printf("UNIX seconds dec: %lld\n", (long long)secs);
      printf("UNIX seconds hex: 0x%llX\n", (unsigned long long)secs);
      printf("UNIX millis  dec: %lld\n", ms);
      printf("UNIX millis  hex: 0x%llX\n", (unsigned long long)ms);
      return 0;
    }
    C# (.NET)
    using System;
    using System.Globalization;
    
    static class UnixHex {
      static bool IsHexLike(string s) => s.StartsWith("0x", true, CultureInfo.InvariantCulture) || s.IndexOfAny("abcdefABCDEF".ToCharArray()) >= 0;
    
      public static DateTimeOffset ParseToUtc(string s, string unit = "auto"){
        s = s.Trim();
        bool neg = s.StartsWith("-");
        string core = s.StartsWith("-0x", true, CultureInfo.InvariantCulture) ? s.Substring(3)
                   : s.StartsWith("0x",  true, CultureInfo.InvariantCulture) ? s.Substring(2)
                   : s;
        long val = Convert.ToInt64((IsHexLike(s)) ? (neg ? "-" + Convert.ToInt64(core,16).ToString() : Convert.ToInt64(core,16).ToString())
                                                  : s, 10);
        string mode = unit;
        if (mode=="auto") mode = (Math.Abs(val) >= 100_000_000_000L) ? "ms" : "s";
        long ms = (mode=="s") ? val*1000L : val;
        return DateTimeOffset.FromUnixTimeMilliseconds(ms);
      }
    }
    Go
    package main
    import (
      "fmt"
      "strconv"
      "strings"
      "time"
    )
    
    func parseIntFlexible(s string) (int64, error) {
      s = strings.TrimSpace(s)
      neg := strings.HasPrefix(s, "-")
      core := s
      if strings.HasPrefix(strings.ToLower(s), "-0x") { core = s[3:]; neg = true }
      if strings.HasPrefix(strings.ToLower(s), "0x")  { core = s[2:] }
      base := 10
      if strings.ContainsAny(core, "abcdefABCDEF") { base = 16 }
      u, err := strconv.ParseUint(strings.TrimPrefix(core, "-"), base, 64)
      if err != nil { return 0, err }
      if neg { return -int64(u), nil }
      return int64(u), nil
    }
    
    func unitAuto(v int64) string {
      if v < 0 { v = -v }
      if v >= 100_000_000_000 { return "ms" }
      return "s"
    }
    
    func main() {
      v, _ := parseIntFlexible("0x6512BD00")
      mode := unitAuto(v)
      if mode == "s" { v = v * 1000 }
      t := time.UnixMilli(v)
      fmt.Println(t.UTC().Format(time.RFC3339Nano))
    }
    Java / Kotlin
    // Java
    import java.time.*;
    import java.util.*;
    
    public class UnixHex {
      static boolean isHexLike(String s){
        return s.startsWith("0x") || s.matches(".*[A-Fa-f].*");
      }
      static long parseFlexible(String s){
        s = s.trim();
        boolean neg = s.startsWith("-");
        String core = s.startsWith("-0x") ? s.substring(3) : (s.startsWith("0x") ? s.substring(2) : s);
        long v = isHexLike(s) ? Long.parseUnsignedLong(core,16) : Long.parseLong(core,10);
        return neg ? -v : v;
      }
      static String unitAuto(long v){ return Math.abs(v) >= 100_000_000_000L ? "ms" : "s"; }
    
      public static void main(String[] args){
        long v = parseFlexible("5F5E100");
        String mode = unitAuto(v);
        long ms = mode.equals("s") ? v*1000L : v;
        Instant inst = Instant.ofEpochMilli(ms);
        System.out.println(inst.toString()); // ISO-8601 UTC
      }
    }
    Rust
    use chrono::{DateTime, Utc, TimeZone};
    
    fn parse_flexible(s: &str) -> i128 {
        let s = s.trim();
        let neg = s.starts_with('-');
        let core = s.strip_prefix("-0x").or_else(|| s.strip_prefix("0x")).unwrap_or(s);
        let mut v: i128 = if s.contains(|c: char| c.is_ascii_hexdigit() && c.is_ascii_alphabetic()) {
            i128::from_str_radix(core, 16).unwrap()
        } else { core.parse().unwrap() };
        if neg { v = -v }
        v
    }
    fn unit_auto(v: i128) -> 'static str { if v.abs() >= 100_000_000_000 { "ms" } else { "s" } }
    
    fn main(){
        let v = parse_flexible("0x0000018EDDDEAD");
        let unit = unit_auto(v);
        let ms: i128 = if unit == "s" { v * 1000 } else { v };
        let secs = (ms.div_euclid(1000)) as i64; // floor
        let nsec = ((ms.rem_euclid(1000)) * 1_000_000) as u32;
        let dt: DateTime<Utc> = Utc.timestamp_opt(secs, nsec).unwrap();
        println!("{}", dt.to_rfc3339_opts(chrono::SecondsFormat::Millis, true));
    }
    PHP
    <?php
    function parse_int_flexible(string $s): int {
      $s = trim($s);
      if (stripos($s, '-0x') === 0) return -intval(substr($s,3), 16);
      if (stripos($s, '0x') === 0)  return intval(substr($s,2), 16);
      if (preg_match('/[a-f]/i', $s)) return intval($s, 16);
      return intval($s, 10);
    }
    function unit_auto(int $v): string {
      return (abs($v) >= 100_000_000_000) ? 'ms' : 's';
    }
    $v = parse_int_flexible('0x6512BD00');
    $mode = unit_auto($v);
    $ms = ($mode === 's') ? $v * 1000 : $v;
    $dt = (new DateTimeImmutable('@' . intdiv($ms,1000)))->setTimezone(new DateTimeZone('UTC'));
    echo $dt->format('c'); // ISO-8601 UTC
    
    Ruby
    def parse_int_flexible(s)
      s = s.strip
      return -s[3..].to_i(16) if s.downcase.start_with?('-0x')
      return s[2..].to_i(16)  if s.downcase.start_with?('0x')
      return s.to_i(16)       if s =~ /[a-f]/i
      s.to_i
    end
    def unit_auto(v) = v.abs >= 100_000_000_000 ? 'ms' : 's'
    
    v = parse_int_flexible('5F5E100')
    mode = unit_auto(v)
    ms = mode == 's' ? v * 1000 : v
    t = Time.at(ms / 1000.0).utc
    puts t.iso8601(3)
    Bash (GNU coreutils)
    # Hex/dec -> ISO UTC (seconds assumed; set UNIT=ms for millis)
    IN="${1:-0x6512BD00}"
    UNIT="${2:-auto}"
    
    # normalize to decimal
    if [[ "$IN" =~ ^-?0x[0-9a-fA-F]+$ ]]; then
      DEC=$((IN))  # bash can parse 0x...
    elif [[ "$IN" =~ [a-fA-F] ]]; then
      DEC=$((16#$IN))
    else
      DEC=$IN
    fi
    
    if [[ "$UNIT" == "auto" ]]; then
      ABS=${DEC#-}
      [[ ${#ABS} -ge 11 ]] && UNIT=ms || UNIT=s
    fi
    
    if [[ "$UNIT" == "ms" ]]; then
      SEC=$(( DEC / 1000 ))
    else
      SEC=$DEC
    fi
    
    date -u -d "@$SEC" +"%Y-%m-%dT%H:%M:%S%z"

    5 Fun Facts about Unix Hex Timestamps

    0xDEADBEEF day

    The hex Easter egg 0xDEADBEEF as seconds lands on 2088-05-20 UTC. People hide it in logs as a playful placeholder.

    Easter egg

    One day is 0x15180

    0x15180 equals 86,400 seconds—one exact day. Handy when eyeballing offsets close to the epoch.

    Mental math

    100 million seconds check

    0x5F5E100 is 100,000,000 seconds, which lands on 1973-03-03. If you see nearby values, you’re in early-70s territory.

    Time anchor

    Y2038 in hex

    The 32-bit signed max 0x7FFFFFFF seconds is 2038-01-19 03:14:07 UTC—the classic overflow moment for old systems.

    2038 watch

    Seconds vs ms by length

    2025-01-01 as seconds is 0x67748580 (8 hex digits). As milliseconds it’s 0x1941F297C00 (11–12 digits). Length alone is a strong unit clue.

    Unit hint

    Explore more tools