How to archive timestamp normaliser online for free
- Step 1Open the Timestamp Normaliser — Go to the tool page at /archive-tools/timestamp-normalizer. Everything runs client-side, so you can even use it offline once the page has loaded — there is no server round-trip for processing.
- Step 2Drop your archive onto the upload zone — Accepts
.zip,.tar,.tar.gz/.tgz,.gz,.bz2,.tar.bz2,.xz,.tar.xz,.7z,.rar, and.iso. One file at a time on Free. The tool detects the format from the file's magic bytes, not the extension, so a mislabelled file still works. - Step 3Pick the Target date — The single option is a date picker labelled Target date, defaulting to
1980-01-01. Leave it on the default for classic reproducible-build behaviour, or choose any other calendar date. Note: it is date-only — there is no hour/minute field, so every entry lands at 00:00:00 UTC of the date you choose. - Step 4Run the normalisation — Click the process button. The tool extracts every file entry, then re-zips them all with the chosen modification time using
fflate.zipSync(..., { mtime }). Empty-directory entries are dropped in the process — only real files are re-packed. - Step 5Check the result metrics — The result panel reports Timestamp (the ISO date applied, e.g.
1980-01-01T00:00:00.000Z) and Entries (how many files were re-packed), plus original vs output size. Verify the entry count matches what you expected before downloading. - Step 6Download <name>-normalized.zip — The output is always a ZIP, named after your input with a
-normalized.zipsuffix. To confirm determinism, run the same input twice and compare hashes — the bytes should match. Use the sibling checksum-generator to print a SHA-256 for proof.
What the Free tier handles
Real limits from the archive tier table. The per-archive entry-count cap matters as much as file size — a folder of thousands of tiny files can hit 500 entries well under 50 MB.
| Tier | Max archive size | Max entries per archive | Files per run | Cost |
|---|---|---|---|---|
| Free | 50 MB | 500 | 1 | Free, no signup |
| Pro | 500 MB | 50,000 | 20 | Paid |
| Pro + Media | 2 GB | 500,000 | 100 | Paid |
| Developer | 2 GB | 500,000 | unlimited | Paid |
What goes in vs what comes out
The normaliser reads many formats but always writes one ZIP. Input format does not round-trip — a tar.gz comes back as a .zip.
| Input you drop | How it is read | What you download |
|---|---|---|
.zip (unencrypted) | fflate unzipSync | <name>-normalized.zip |
.tar, .tar.gz, .tgz, .gz | fflate (tar parser + gunzip) | <name>-normalized.zip |
.7z, .rar, .bz2, .xz, .iso | libarchive WASM (read-only) | <name>-normalized.zip |
.zip with encrypted entries | needs a password — not offered here | Fails (no password option) |
The one option you control
There is exactly one setting. No compression-level, no per-entry, no time-of-day controls exist — claims to the contrary are wrong.
| Control | Type | Default | Effect |
|---|---|---|---|
| Target date | Date picker (date-only) | 1980-01-01 | Applied to every entry as 00:00:00 UTC |
Cookbook
Concrete runs showing the input, the option, and the observable result. Hashes are illustrative.
Make two builds produce the same ZIP hash
The classic reason to use this tool. Build A and Build B contain identical files but were packed seconds apart, so their entry mtimes differ and their hashes differ. Normalise both to the same date and the hashes converge.
Before: build-a.zip sha256: 9f12...a7 (mtime 2026-06-10 14:02) build-b.zip sha256: c4e8...3b (mtime 2026-06-10 14:03) Drop each, Target date = 1980-01-01 (default), download: build-a-normalized.zip sha256: 71bd...0e build-b-normalized.zip sha256: 71bd...0e <-- identical
Use today's date instead of the epoch
Not every workflow wants 1980. If you want a human-readable release date on every entry, set the picker to a real date. Every file lands at midnight UTC of that day.
Target date: 2026-06-10 Result metrics: Timestamp: 2026-06-10T00:00:00.000Z Entries: 42 Every file in release-2026-06-10-normalized.zip now shows 10 Jun 2026 00:00 as its modification time.
Normalise a tar.gz and get a ZIP back
A Linux release tarball goes in; a normalised ZIP comes out. The tool gunzips, parses the tar, then re-packs into ZIP. Useful when the consumer expects a ZIP anyway.
Input: app-1.4.0.tar.gz (137 entries) Target date: 1980-01-01 Download: app-1.4.0.tar-normalized.zip Timestamp: 1980-01-01T00:00:00.000Z Entries: 137 Note: the .tar.gz did NOT round-trip; output is .zip.
Prove determinism with a checksum
Run the same input twice and hash both outputs to confirm the tool is deterministic for your archive. Pair with the checksum-generator sibling.
1. Drop project.zip -> project-normalized.zip (run 1)
2. Drop project.zip -> project-normalized.zip (run 2)
3. /archive-tools/checksum-generator on each:
run 1: SHA-256 3aa1...9c
run 2: SHA-256 3aa1...9c <-- match = deterministicStrip both timestamps and a wrapper folder
GitHub-style downloads wrap everything in a top-level folder AND carry checkout timestamps. Normalise the dates here, then flatten the folder with the sibling path-prefix-remover.
Step 1 - timestamp-normalizer: repo-main.zip -> repo-main-normalized.zip (all mtimes = 1980-01-01) Step 2 - /archive-tools/path-prefix-remover: strip "repo-main/" -> repo-main-flattened.zip Now the bundle is both date-stable and prefix-free.
Edge cases and what actually happens
Output is always a ZIP, never the input format
By designWhatever you drop — tar.gz, 7z, rar — the tool re-packs into a single .zip. There is no option to keep the original container. If you need a tar.gz back, normalise here first, then convert with a sibling such as zip-to-tar-gz.
All entries get the SAME date — no per-entry times survive
ExpectedThis is not a 'fix the broken ones' tool; it overwrites every modification time with the one date you picked. If you need to keep relative ordering between files, this tool is the wrong choice — its entire purpose is to flatten all times to a single canonical value.
Time-of-day cannot be set
By designThe control is an HTML date picker with no hour/minute field, and YYYY-MM-DD is parsed as UTC midnight. Every entry therefore reads 00:00:00 UTC of the chosen date. There is no way to stamp, say, 14:30 — only the calendar date.
Empty-directory entries are dropped
Not preservedDuring extraction the tool keeps only real file entries (names not ending in /), so empty folders present purely as directory markers in the source ZIP will not appear in the output. Files inside folders keep their paths; only standalone empty-directory records are lost.
Encrypted ZIP entries
FailThe normaliser exposes no password field, so an archive containing AES-256 or ZipCrypto encrypted entries cannot be read and the run fails. Decrypt first (extract with the password using multi-format-extractor), then normalise the plaintext result.
Invalid Target date
Invalid date errorIf the date value cannot be parsed into a real Date, processing throws Invalid target timestamp. In normal use the date picker only emits valid YYYY-MM-DD values, so this surfaces mainly via the automation/runner path with a malformed string.
Archive over 50 MB on Free
Tier limitFree is capped at 50 MB per archive. A larger bundle is rejected with an upgrade prompt. Pro raises the cap to 500 MB; Pro + Media and Developer reach 2 GB. The cap is on the input archive size, checked before processing.
More than 500 entries on Free
Tier limitThere is also a per-archive entry-count cap: 500 on Free, 50,000 on Pro, 500,000 on Pro + Media / Developer. A directory of thousands of tiny files can hit the entry cap while staying well under the size cap, so watch both numbers.
Re-compression changes output size
ExpectedBecause the tool extracts and re-zips at DEFLATE level 6, the output ZIP's byte size can differ from the input even though the file contents are identical — a store (level 0) input becomes compressed, and a differently-tuned source ZIP is re-encoded. The data is unchanged; only the container compression is uniform.
Unrecognised or non-archive file
Format errorIf the magic bytes match no supported archive and a last-resort ZIP parse also fails, the tool reports Could not detect or extract archive format. Confirm the file really is one of the supported archive types before retrying.
Frequently asked questions
Is this really free and is there an upload?
Yes to free, no to upload. The tool processes archives up to 50 MB / 500 entries on the Free tier with no signup and no cost. All reading and re-packing happens in your browser via fflate and libarchive WASM — your archive never reaches a server. The only thing recorded server-side is a usage counter with no file content.
What formats can I drop in?
ZIP, TAR, GZIP, tar.gz/tgz, tar.bz2, tar.xz, bz2, xz, 7z, RAR, and ISO. ZIP/GZIP/TAR are read with fflate; 7z/RAR/bz2/xz/ISO go through the libarchive WASM bridge (read-only). The format is detected from magic bytes, so a wrong extension still works.
What do I get back?
Always a single .zip named <your-file>-normalized.zip, re-compressed with DEFLATE. The input container type does not survive — a tar.gz or 7z comes back as a ZIP. If you need a different output container, convert afterwards with a sibling tool.
What's the default date and why 1980?
The default is 1980-01-01, the MS-DOS / ZIP epoch — the earliest date the ZIP format can represent. Many reproducible-build systems standardise on it so checksums match across machines, which is why it is the sensible default here.
Can I set a time of day, not just a date?
No. The control is a date-only picker; the chosen YYYY-MM-DD is applied as 00:00:00 UTC to every entry. There is no hour/minute option.
Does it keep the original modification time of each file?
No — that is the opposite of what it does. Every entry is overwritten with the single date you pick. The goal is one canonical timestamp for the whole archive, not preservation.
Will my files' contents change?
No. Only the modification-time metadata is replaced. File bytes are extracted and re-packed verbatim. The output ZIP's overall size may differ because it is re-compressed at level 6, but each file's content is identical.
Why did my empty folders disappear?
The extractor keeps only real file entries, so directory-marker records for empty folders are not carried into the output. Folders that contain files keep their paths intact; only standalone empty-directory entries are dropped.
It says my archive is too big — what now?
You hit a tier cap: 50 MB / 500 entries on Free. Either trim the archive, or upgrade — Pro allows 500 MB / 50,000 entries, and Pro + Media / Developer reach 2 GB / 500,000 entries. Both size and entry count are checked, so a huge file count can trip the limit under the size cap.
Can it normalise an encrypted ZIP?
No. This tool has no password field, so encrypted entries cannot be read and the run fails. Extract the archive with its password using multi-format-extractor first, then normalise the plaintext output.
How do I prove the output is deterministic?
Run the same input twice and hash both outputs with checksum-generator. Identical SHA-256 values confirm the normaliser produced byte-identical archives for your input.
What else pairs well with this?
For end-to-end reproducibility, combine it with path-prefix-remover to strip wrapper folders, filename-sanitizer to canonicalise paths, and archive-diff to compare two normalised archives entry-by-entry.
Privacy first
Every JAD Archive tool runs entirely in your browser using fflate, @zip.js/zip.js, and the libarchive WASM bridge. Your archives never leave your device — verified by zero outbound network requests during processing.