Zerowidth CleanerAll measured guides

CLAUDE WATERMARK REMOVER · PRACTICAL TEST

Why does changing January 31 to month one produce March 3?

In our non-leap-year fixture setUTCMonth(1) keeps the day number 31 and overflows into March 3. January 28 reaches February 28; January 29 reaches March 1. Cleanup repairs the day spelling but does not clamp month arithmetic.

Tested October 26, 2026 · v24.22.1 · 4 measured runs

Open the Claude text cleaner · Full measured data

Code-point comparison for Marked day

Measured inputs and outputs

These are locally constructed test strings, not evidence that Claude inserts these characters. We executed the saved homepage script snapshot with a minimal DOM harness and compared exact strings. The invisible-checkbox state and dash mode appear in each row. The observations below test this page's specific question. Destination observations run independently on the exact input and cleaned strings in the recorded Node runtime. We make no detector-score or statistical-watermark removal claim.

Before and after observations; full code points and strings are in the JSON download.
Fixture and modeInput string and code pointsOutput and cleaner statusObserved before / after
Marked day
direct string / keep / invisible true
"3​1"
U+0033 U+200B U+0031
"31"
Removed 1 invisible character
{"day":"NaN","initial":"Invalid Date","after":"Invalid Date","utcMonth":null}
{"day":"31","initial":"2025-01-31T00:00:00.000Z","after":"2025-03-03T00:00:00.000Z","utcMonth":2}
January 31
direct string / keep / invisible true
"31"
U+0033 U+0031
"31"
No selected invisible characters found
{"day":"31","initial":"2025-01-31T00:00:00.000Z","after":"2025-03-03T00:00:00.000Z","utcMonth":2}
{"day":"31","initial":"2025-01-31T00:00:00.000Z","after":"2025-03-03T00:00:00.000Z","utcMonth":2}
January 28
direct string / keep / invisible true
"28"
U+0032 U+0038
"28"
No selected invisible characters found
{"day":"28","initial":"2025-01-28T00:00:00.000Z","after":"2025-02-28T00:00:00.000Z","utcMonth":1}
{"day":"28","initial":"2025-01-28T00:00:00.000Z","after":"2025-02-28T00:00:00.000Z","utcMonth":1}
January 29
direct string / keep / invisible true
"29"
U+0032 U+0039
"29"
No selected invisible characters found
{"day":"29","initial":"2025-01-29T00:00:00.000Z","after":"2025-03-01T00:00:00.000Z","utcMonth":2}
{"day":"29","initial":"2025-01-29T00:00:00.000Z","after":"2025-03-01T00:00:00.000Z","utcMonth":2}

The setter retains a day that February cannot contain

The observer starts from 2025-01-01 at midnight UTC, sets its UTC day from the supplied text, then changes only its UTC month to one. The marked 31 initially converts to NaN, leaving Invalid Date. After cleanup it becomes January 31 before the month change, and March 3 afterward. The plain 31 reference reproduces this path directly. The result month diagnostic is two, using the zero-based JavaScript month numbering. This is a mutable Date setter sequence; no text parser decides what a nonexistent February 31 should mean.

Adjacent day controls reveal the overflow boundary

January 28 reaches February 28 with UTC month one. January 29 reaches March 1 with UTC month two. Both controls use the same fixed year, which has 28 days in February. The differing results arise from retaining the original day while changing the month. We save the intermediate ISO timestamp as well as the final one, so the input day is visible before arithmetic. None of these observations depends on the machine local time zone or a daylight-saving transition because every construction and mutation in the observer is UTC based.

Choose overflow or clamping as a calendar policy

For an application that means the last available day of the requested month, define that policy explicitly rather than assuming this setter performs it. An overflow policy and a clamping policy can produce different schedule dates. This fixture demonstrates the built-in overflow behavior but does not implement recurrence rules, a monthly billing calendar or a date library. It tests only January in one non-leap year. Other source months, leap years, negative month arguments and separate day parameters require their own checks before generalizing a scheduling implementation.

Keep character repair apart from calendar semantics

The actual homepage callback deletes the inserted U+200B from a numeric day string. It does not receive the Date object or advance a calendar. A valid cleaned number can still lead to a date the caller did not intend if its arithmetic policy is implicit. Earlier ISO coverage asks whether strings parse; this page starts from an explicit timestamp and observes a setter preserving the day. All dates are synthetic test fixtures, with no external calendar changed. These results provide no evidence about Claude source attribution or model-level watermark removal.

Reproduce this test

Save reproduce.cjs and tested-app.js in the same folder. Run the command below with Node.js. The harness prints its runtime, script SHA-256 and every measured row. Compare those rows with the original record. Using a newer script or runtime creates a new experiment; retain the version information with your rerun.

node reproduce.cjs

Reference and next check

ECMAScript Date.prototype.setUTCMonth provides the relevant primary definition. The table and fixture analysis are original measurements. For broader inspection, use our Unicode inspector. Read the scope distinction before interpreting cleanup as a watermark result.