⭐ Starlight Tools / Unix Hex Timestamp

Unix Hex Timestamp Converter

Convert Unix timestamps in hex (0x…) or decimal — auto-detects seconds vs milliseconds with a manual override. Fully client-side.

Related Tools

UNIX Timestamp Converter · LDAP / FILETIME Converter · Apple Cocoa / Core Foundation Time · Time Since / Until

Results always include UTC; this controls the extra local view.
Override if your data source is known to be seconds or ms.

1) Hex / Decimal Unix Timestamp → Date

Hex with/without 0x is accepted. Negative values supported.

2) Date → Unix Timestamp (Hex & Decimal)

Interpreted in your current local time zone.
If an offset is provided, it will be respected.

About Unix Hex Timestamps

A Unix timestamp is the number of seconds (or milliseconds) since 1970-01-01T00:00:00Z. Many tools and logs render this number in hexadecimal. This converter accepts hex (with or without 0x) or decimal, detects whether the value is in seconds or milliseconds, and shows both formats.

  • Auto-detect: Large magnitudes (≈ ≥ 1e11, i.e., ms) are treated as milliseconds; smaller as seconds. You can override.
  • Signed / negative: Values before 1970 (negative) are supported.
  • Precision: Internals use BigInt to avoid rounding. Display is to millisecond precision.

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"