@master4n/temporal-transformer

Convert any epoch timestamp to a human-readable date in TypeScript — auto-detects seconds, milliseconds, microseconds, and nanoseconds with zero configuration. Also converts date strings to epoch, computes calendar-accurate durations, and handles any IANA timezone.
v2.0 is out. Engine swapped from moment.js to Luxon — same API, ~60% smaller bundle (~71 KB vs ~180 KB), no maintenance-mode dependency. Upgrade with npm i @master4n/temporal-transformer@2 and run npx @master4n/temporal-transformer-codemod ./src to migrate format strings automatically. See MIGRATION.md.
Why temporal-transformer?
Working with epoch timestamps in TypeScript is surprisingly painful:
- You don't know if a value is in seconds, milliseconds, microseconds, or nanoseconds until it breaks in production.
new Date(epoch) silently produces wrong dates if the unit is wrong.
- Parsing date strings without a format string is unreliable and locale-dependent.
- Getting the UTC offset for a given timezone requires knowing a timezone library's specific API.
temporal-transformer solves all of these in one small, fully-typed package:
convertEpoch(1622547800).dateTime;
convertEpoch(1622547800000).dateTime;
convertEpoch(1622547800000000).dateTime;
convertEpoch(1622547800000000000).dateTime;
Features
- Auto-detects epoch unit — seconds, milliseconds, microseconds, nanoseconds
- Epoch → human-readable date in local timezone and GMT simultaneously
- Date string → epoch with explicit format and timezone (strict parsing, no surprises)
- Calendar-accurate duration between two timestamps (years, months, days, hours, minutes, seconds)
- Timezone conversion — format any epoch in any IANA timezone
- Timezone utilities — list all available IANA timezones, get UTC offset for any zone
- Result-style safe API — every function has a
safeXxx variant returning { ok, value | error } instead of throwing
- Safe predicates —
isValidEpoch / isValidTimezone that never throw
- Frozen results — returned objects are
Object.freeze()'d to prevent downstream tampering
- Token allowlist — format strings are validated against a Luxon-token allowlist; typos throw
FormatInvalid instead of silently producing garbage
- Relative time — "3 hours 15 minutes ago" / "2 days from now"
- Full TypeScript support — strict types, enums, and interfaces exported
- Dual ESM + CJS build — works in Next.js, Node.js, Vite, webpack
- Hardened input validation — DoS-capped string and format lengths, rejects HTML/XSS payloads,
Infinity, NaN, prototype-pollution attempts, and clock-corruption edge cases
- Powered by Luxon — immutable, IANA-aware via the
Intl API, no moment.js, Node 18+
Installation
npm install @master4n/temporal-transformer
yarn add @master4n/temporal-transformer
pnpm add @master4n/temporal-transformer
Quick Start
import {
convertEpoch,
convertDateToEpoch,
convertEpochToTimezone,
parseToEpoch,
getDurationBetween,
isValidEpoch,
} from '@master4n/temporal-transformer';
const result = convertEpoch(1622547800000);
console.log(result.dateTime);
console.log(result.dateTimeInGMT);
console.log(result.epochUnit);
console.log(result.relative);
const epoch = convertDateToEpoch(new Date(), 'America/New_York');
console.log(epoch.epochInSeconds);
console.log(epoch.epochInMilliseconds);
const parsed = parseToEpoch('2024-12-25T00:00:00', undefined, 'Asia/Kolkata');
console.log(parsed.epochInMilliseconds);
const formatted = convertEpochToTimezone(1622547800000, 'Asia/Tokyo', 'yyyy-MM-dd HH:mm');
console.log(formatted);
const duration = getDurationBetween(1609459200000, 1622547800000);
console.log(duration.humanReadable);
console.log(isValidEpoch(1622547800000));
console.log(isValidEpoch('bad value'));
console.log(isValidEpoch(Infinity));
API Reference
convertEpoch(epoch, format?)
Converts any epoch value to a human-readable date. Automatically detects the epoch unit (seconds / milliseconds / microseconds / nanoseconds).
function convertEpoch(epoch: number, format?: string): EpochToDate
epoch | number | — | Epoch value in any unit |
format | string | 'yyyy-MM-dd HH:mm:ss.SSS' | Luxon format token (validated against SUPPORTED_FORMAT_TOKENS) |
Returns: EpochToDate
const result = convertEpoch(1622547800000, 'yyyy-MM-dd');
convertDateToEpoch(date, timezone?)
Converts a Date object to epoch values (seconds and milliseconds) in the specified timezone.
function convertDateToEpoch(date: Date, timezone?: string): DateToEpoch
date | Date | — | Any valid JavaScript Date |
timezone | string | System local timezone | IANA timezone name |
Returns: DateToEpoch
const result = convertDateToEpoch(new Date('2024-01-15'), 'America/New_York');
convertEpochToTimezone(epoch, timezone, format?)
Formats an epoch value as a date string in a specific IANA timezone.
function convertEpochToTimezone(epoch: number, timezone: string, format?: string): string
convertEpochToTimezone(1622547800000, 'America/Los_Angeles', 'yyyy-MM-dd HH:mm:ss');
convertEpochToTimezone(1622547800000, 'Asia/Tokyo');
getEpochUnit(epoch)
Returns just the detected unit of an epoch value — useful for routing logic without doing the full conversion.
function getEpochUnit(epoch: number | string): EpochUnit
getEpochUnit(1622547800);
getEpochUnit(1622547800000);
getEpochUnit(1622547800000000);
getEpochUnit(1622547800000000000);
parseToEpoch(input, format?, timezone?)
Parses a date string into epoch values. Uses strict parsing when a format is provided — never silently produces a wrong date.
function parseToEpoch(input: string, format?: string, timezone?: string): DateToEpoch
input | string | — | Date string to parse |
format | string or undefined | Auto (ISO 8601) | Luxon format token (validated against SUPPORTED_FORMAT_TOKENS) |
timezone | string | System local timezone | IANA timezone to interpret the date in |
Returns: DateToEpoch
Throws: EpochValidationError with EpochError.ParseError if the string cannot be parsed, or EpochError.TimezoneError for an unknown timezone.
parseToEpoch('2024-12-25T00:00:00Z');
parseToEpoch('25/12/2024', 'dd/MM/yyyy', 'Europe/London');
parseToEpoch('2024-12-25 09:00:00', 'yyyy-MM-dd HH:mm:ss', 'Asia/Kolkata');
getDurationBetween(fromEpoch, toEpoch)
Computes a calendar-accurate duration between two epoch timestamps.
function getDurationBetween(fromEpoch: number, toEpoch: number): ParsedDuration
Returns: ParsedDuration
Throws: EpochValidationError with EpochError.RangeError if fromEpoch > toEpoch.
const d = getDurationBetween(1609459200000, 1748000000000);
console.log(d.years);
console.log(d.months);
console.log(d.days);
console.log(d.humanReadable);
console.log(d.totalMilliseconds);
Calendar-accurate: months and years account for actual calendar boundaries (Feb 28/29, 30/31-day months), not fixed 30.44-day approximations.
getTimezoneOffset(timezone, epoch?)
Returns the UTC offset for an IANA timezone, optionally at a specific point in time (useful for DST-aware offsets).
function getTimezoneOffset(timezone: string, epoch?: number): TimezoneOffset
getTimezoneOffset('Asia/Kolkata');
getTimezoneOffset('America/New_York');
getTimezoneOffset('America/New_York', 1622547800000);
getTimezoneList()
Returns the full list of supported IANA timezone names (600+).
function getTimezoneList(): string[]
const zones = getTimezoneList();
zones.includes('Asia/Kolkata');
zones.includes('America/Chicago');
getEpochNow()
Returns the current moment as epoch values (seconds, milliseconds, ISO string, and detected timezone).
function getEpochNow(): EpochNow
const now = getEpochNow();
formatDuration(milliseconds)
Formats a duration in milliseconds as a human-readable string.
function formatDuration(milliseconds: number): string
formatDuration(3661000);
formatDuration(86400000);
formatDuration(90061000);
formatDuration(500);
isValidEpoch(epoch) · isValidTimezone(timezone)
Safe predicates that return boolean without throwing. Useful for conditional logic and input validation at system boundaries.
function isValidEpoch(epoch: unknown): boolean
function isValidTimezone(timezone: string): boolean
isValidEpoch(1622547800000);
isValidEpoch('1622547800000');
isValidEpoch(null);
isValidEpoch(Infinity);
isValidEpoch(NaN);
isValidTimezone('UTC');
isValidTimezone('Asia/Kolkata');
isValidTimezone('Not/ATimezone');
Types Reference
EpochToDate
interface EpochToDate {
epoch: number;
epochUnit: string;
timezone: string;
dateTime: string;
dateTimeInGMT: string;
relative: string;
}
DateToEpoch
interface DateToEpoch {
epochInSeconds: number;
epochInMilliseconds: number;
timezone: string;
dateTime: string;
dateTimeInGMT: string;
}
ParsedDuration
interface ParsedDuration {
years: number;
months: number;
days: number;
hours: number;
minutes: number;
seconds: number;
milliseconds: number;
totalMilliseconds: number;
humanReadable: string;
}
EpochNow
interface EpochNow {
seconds: number;
milliseconds: number;
iso: string;
timezone: string;
}
TimezoneOffset
interface TimezoneOffset {
offset: string;
offsetMinutes: number;
}
EpochUnit enum
enum EpochUnit {
SECONDS = 'seconds',
MILLI_SECONDS = 'milliseconds',
MICRO_SECONDS = 'microseconds',
NANO_SECONDS = 'nanoseconds',
}
DurationUnit type
type DurationUnit =
| 'years' | 'months' | 'weeks' | 'days'
| 'hours' | 'minutes' | 'seconds' | 'milliseconds';
Epoch Unit Auto-Detection
< 10,000,000,000 | seconds | 1622547800 |
< 10,000,000,000,000 | milliseconds | 1622547800000 |
< 10,000,000,000,000,000 | microseconds | 1622547800000000 |
< 1e19 | nanoseconds | 1622547800000000000 |
Negative epochs (dates before Unix epoch, i.e. before 1970-01-01) are fully supported.
Error Handling
All functions throw EpochValidationError (extends Error) with a message from the EpochError enum.
import { EpochValidationError, EpochError } from '@master4n/temporal-transformer';
try {
convertEpoch(null as any);
} catch (err) {
if (err instanceof EpochValidationError) {
console.log(err.message);
console.log(err.name);
}
}
UndefinedOrNull | Input is null or undefined |
NotANumber | Input is not numeric, is Infinity, or is NaN |
Empty | Input is an empty or whitespace-only string |
EpochUnit | Epoch value is too large to classify into any unit |
DateError | Date object passed to convertDateToEpoch is invalid |
TimezoneError | Timezone string is not a recognized IANA timezone |
ParseError | Date string cannot be parsed (in parseToEpoch) |
RangeError | fromEpoch > toEpoch in getDurationBetween |
Result-Style Safe API (unique feature)
Every function has a safeXxx counterpart that returns a discriminated Result<T> object instead of throwing. This is ideal for code paths handling untrusted input — API endpoints, form validation, batch processors — where try/catch becomes noise.
import { safeConvertEpoch, safeParseToEpoch, safeGetEpochNow } from '@master4n/temporal-transformer';
const result = safeConvertEpoch(req.body.timestamp);
if (result.ok) {
console.log(result.value.dateTime);
} else {
console.log(result.error.message);
}
safeConvertEpoch | convertEpoch | Result<EpochToDate, EpochValidationError> |
safeConvertDateToEpoch | convertDateToEpoch | Result<DateToEpoch, EpochValidationError> |
safeConvertEpochToTimezone | convertEpochToTimezone | Result<string, EpochValidationError> |
safeParseToEpoch | parseToEpoch | Result<DateToEpoch, EpochValidationError> |
safeGetDurationBetween | getDurationBetween | Result<ParsedDuration, EpochValidationError> |
safeGetTimezoneOffset | getTimezoneOffset | Result<TimezoneOffset, EpochValidationError> |
safeGetEpochNow | getEpochNow | Result<EpochNow, EpochValidationError> |
safeGetEpochUnit | getEpochUnit | Result<EpochUnit, EpochValidationError> |
The Result<T> type
type Result<T, E = Error> =
| { ok: true; value: T; error?: never }
| { ok: false; value?: never; error: E };
The discriminant is ok. TypeScript narrows value and error automatically once you branch on it.
Security Model
temporal-transformer treats every input as untrusted. The library has been audited against the OWASP-style threat model below; the test suite test/epoch/security.test.ts pins each defense.
Threats addressed
Prototype pollution via __proto__ | Object inputs are rejected with NotANumber before any property access |
Infinity, -Infinity, NaN | Explicit isFinite guard, throws NotANumber |
| String DoS (e.g. 1M-char numeric string) | MAX_INPUT_STRING_LENGTH = 256 → throws InputTooLong |
| Format-string DoS (memory amplification) | MAX_FORMAT_STRING_LENGTH = 256 → throws FormatTooLong |
XSS / HTML in parseToEpoch | Character allowlist regex rejects payloads before reaching moment |
| Stderr leakage of payloads | Strict ISO 8601 mode bypasses moment's js Date() fallback path |
| Timezone injection | validTimezone checks input against the IANA name list |
| Result object tampering | All return values are Object.freeze()'d |
| Internal array mutation | getTimezoneList returns a defensive copy |
System clock corruption (Date.now()) | getEpochNow validates against ±MAX_EPOCH_MS, throws ClockOutOfRange |
| Reversed-range duration | getDurationBetween throws RangeError if from > to |
| ReDoS | All regexes are linear-time (no nested quantifiers, no backreferences) |
Known caller responsibilities
- Format string output is literal: moment's
[bracketed] literals in a format string are emitted verbatim. If you pass user-controlled format strings and output the result to HTML, you must HTML-escape on output. The library does not interpret format strings as user-supplied content.
convertDateToEpoch(date) trusts date.getTime(): a Date subclass with an overridden valueOf()/getTime() returns whatever those methods return. Validate instanceof Date and untainted construction at your trust boundary if this matters.
Exported security constants
import {
MAX_EPOCH_MS,
MIN_EPOCH_MS,
MAX_INPUT_STRING_LENGTH,
MAX_FORMAT_STRING_LENGTH,
} from '@master4n/temporal-transformer';
Reporting
If you discover a security issue, please open a private advisory on github.com/Master4Novice/temporal-transformer/security rather than a public issue. See SECURITY.md for the full policy.
Benchmarks
Real numbers, run yourself with npm run bench. See bench/RESULTS.md for the full report. Headline on Node 24 / Apple Silicon:
getEpochUnit (auto-detect) | — | — | 170M ops/s | the unique feature is essentially free |
isValidEpoch (safe predicate) | 227M ops/s | — | 167M ops/s | 1.4× — JIT-friendly |
convertEpochToTimezone | — | 183K ops/s | 168K ops/s | 1.1× — thin wrapper |
getDurationBetween (calendar) | — | 87K ops/s | 92K ops/s | actually faster than raw Luxon diff |
parseToEpoch (ISO + allowlist) | 7.76M ops/s | 603K ops/s | 219K ops/s | 35× over native (security cost) |
convertEpoch (dual-TZ + relative) | 2.08M ops/s | 527K ops/s | 25K ops/s | 82× — does dual-TZ format + relative time |
What these numbers mean for your code
| Backend ingest / API endpoints (10K req/s) | Imperceptible. Use freely. |
| Per-request formatting (handful of calls) | Network/DB latency dominates by 1000×. |
| Batch processing 100K+ rows/second | convertEpoch is hot — use getEpochUnit once to determine units, then loop with raw Date. |
| Frontend display | Imperceptible. |
Bottom line: This library is a validation + ergonomics layer. Its job is to be correct (auto-detect, security guards, frozen results, Result API) — not to be the fastest format-string emitter. The auto-detect itself is essentially free; the cost is the dual-output convenience and the safety checks.
Comparison with other date libraries
| Auto-detect epoch unit | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
Result-style safe API ({ok, value|error}) | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Frozen results (immutable by construction) | ✅ | ❌ | ✅ | ✅ | ✅ | n/a |
| Input length DoS caps | ✅ | ❌ | ❌ | ❌ | ❌ | n/a |
| Format-token allowlist (rejects typos) | ✅ | ❌ | ❌ | ❌ | ❌ | n/a |
| HTML/XSS payload rejection in parse | ✅ | ❌ | ❌ | ❌ | ❌ | n/a |
| IANA timezone support | ✅ (Intl) | ✅ (bundled) | plugin | plugin | ✅ (Intl) | partial |
| TypeScript-first | ✅ | ❌ (@types/moment) | ✅ | ✅ | ✅ | ✅ |
| Tree-shakeable | partial | ❌ | ✅ | ✅ | partial | n/a |
| Min+gzip size | ~25 KB + Luxon | ~290 KB w/tz | ~7 KB | ~13 KB (modular) | ~71 KB | 0 |
| Maintenance status | active | maintenance-only | active | active | active | spec |
| Best for | Ingesting untrusted, mixed-unit epochs | Legacy codebases | Lightweight client bundles | Functional/modular use | Heavy timezone work | Trivial / known-format use |
When to pick what
- Pick
temporal-transformer if you process timestamps where the unit isn't known up front, or you handle untrusted input and want the safe Result API.
- Pick
dayjs if bundle size is paramount and you don't need timezone-aware parsing.
- Pick
date-fns if you want a treeshakeable, functional API and you control the input.
- Pick
luxon directly if you already know your epoch unit and need raw speed for timezone formatting at scale.
- Pick
Date directly if your input is always milliseconds, you don't care about timezones beyond UTC, and you live by toISOString().
- Pick
moment only if you're maintaining an existing codebase that depends on it.
Common Recipes
Convert a Unix timestamp from an API response
const ts = apiResponse.created_at;
const { dateTime, epochUnit } = convertEpoch(ts);
Validate a user-provided timestamp before processing
const userInput = req.body.timestamp;
if (!isValidEpoch(userInput)) {
return res.status(400).json({ error: 'Invalid timestamp' });
}
const { dateTime } = convertEpoch(Number(userInput));
Show how long ago something happened
const { relative } = convertEpoch(event.createdAt);
console.log(`Event created ${relative}`);
Parse a date string from a form input
const { epochInMilliseconds } = parseToEpoch('25/12/2024', 'dd/MM/yyyy', 'Europe/London');
Compute how long a job ran
const duration = getDurationBetween(job.startedAt, job.finishedAt);
console.log(`Job ran for ${duration.humanReadable}`);
Changelog
2.0.2
- CI fix: Build now succeeds on Node 18 and on all Windows runners. The
@rollup/plugin-terser dependency was transitively pulling serialize-javascript which calls crypto.randomUUID() from globals at module load — this throws ReferenceError: crypto is not defined in Node 18 CJS contexts and on Windows runners. Dropped the terser plugin entirely; the bundle is still tiny (~7.5 KB gzipped). Downstream bundlers can re-minify if needed.
- CI: Workflow now triggers on
master, main, and v1.x-maintenance (was only main). Added workflow_dispatch for manual runs.
- CI: Set
FORCE_JAVASCRIPT_ACTIONS_TO_NODE24=true to silence the Node 20 deprecation warning ahead of the 2026-09-16 removal.
- DX: Test scripts are now cross-platform. Added
cross-env for TZ=UTC and simplified jest invocations to rely on jest.config.mjs for ignore patterns.
- No runtime API changes — drop-in upgrade from 2.0.1.
2.0.1
- Docs: Repository, homepage, and bug-tracker URLs now point at the new public single-package repos at Master4Novice/temporal-transformer and Master4Novice/temporal-transformer-codemod (previously pointed at a private monorepo).
- Docs: Added benchmark suite (
npm run bench) with results published in bench/RESULTS.md. Headline: getEpochUnit ~170M ops/s, getDurationBetween slightly faster than raw Luxon diff, convertEpoch 82× slower than raw Date.toISOString() (cost of dual-TZ + relative-time).
- Docs: New comparison matrix vs moment / dayjs / date-fns / luxon / native
Date with explicit "when to pick what" guidance.
- Docs: Added
SECURITY.md, CONTRIBUTING.md, GitHub issue & PR templates.
- CI: Workflow now runs on Ubuntu/macOS/Windows × Node 18/20/22/24.
- No code changes — behavior identical to v2.0.0.
2.0.0
- Engine swap: moment + moment-timezone → Luxon. ~60% smaller bundle (~71 KB vs ~180 KB), no maintenance-mode dependency.
- Breaking: Format-string grammar is now Luxon syntax. Use
yyyy-MM-dd instead of YYYY-MM-DD, cccc instead of dddd, 'literal' instead of [literal], and so on. Run the migration codemod: npx @master4n/temporal-transformer-codemod ./src.
- Breaking: Default format is now
'yyyy-MM-dd HH:mm:ss.SSS' (was 'YYYY-MM-DD HH:mm:ss.SSSSSS'). JS Date has millisecond precision; the 6-digit fractional was always zero-padded fiction.
- New error:
EpochError.FormatInvalid — thrown when a format string contains a token outside the allowlist. Typos like 'YYYY' (still moment syntax) now surface immediately instead of producing garbage output.
- New exports:
DEFAULT_FORMAT, SUPPORTED_FORMAT_TOKENS (the runtime-enforced allowlist).
- New companion package:
@master4n/temporal-transformer-codemod — one-shot CLI that rewrites moment-style format strings in your codebase. Handles greedy token matching, [literal] → 'literal' escape conversion (with proper '' escaping for embedded quotes), and emits warnings for tokens with no Luxon equivalent (X, x, Q).
- Requirement: Node 18+ (for
Intl.supportedValuesOf).
- Maintenance: v1.x stays on npm under the
legacy dist-tag; install with npm i @master4n/temporal-transformer@legacy. Security backports continue on v1.x-maintenance for 12 months.
See MIGRATION.md for the full upgrade guide.
1.4.0
- Test infrastructure: Added golden-test baseline (
test/golden/) pinning v1.x behavior for the v2.0 parity gate. No runtime behavior changes.
1.3.0
- New (unique): Result-style safe API — every function has a
safeXxx counterpart returning { ok, value | error } instead of throwing (8 functions, see Result-Style Safe API)
- New:
getEpochUnit(epoch) — standalone helper that returns just the detected EpochUnit
- Security: Frozen result objects (
Object.freeze) prevent downstream tampering
- Security:
MAX_INPUT_STRING_LENGTH (256) caps DoS via outsized numeric/date strings — throws InputTooLong
- Security:
MAX_FORMAT_STRING_LENGTH (256) caps memory-amplification via format strings — throws FormatTooLong
- Security:
getEpochNow validates Date.now() against MIN_EPOCH_MS / MAX_EPOCH_MS and throws ClockOutOfRange instead of a raw RangeError on a corrupted system clock
- Security:
getTimezoneList returns a defensive copy, preventing mutation of the shared internal array
- Security:
parseToEpoch now rejects non-string input early with ParseError
- Security: Fallback to
'UTC' when moment.tz.guess() returns an empty string
- New exports:
Result<T, E>, MAX_EPOCH_MS, MIN_EPOCH_MS, MAX_INPUT_STRING_LENGTH, MAX_FORMAT_STRING_LENGTH, EpochThreshold
- New errors:
EpochError.InputTooLong, EpochError.FormatTooLong, EpochError.ClockOutOfRange
- Docs: New Security Model section enumerating the threat model and defenses
1.2.1
- Security fix:
parseToEpoch now validates input against an allowlist of date-safe characters before passing to moment, preventing HTML/XSS payloads from reaching moment's internal parser and appearing in stderr stack traces
- Security fix:
parseToEpoch without an explicit format now uses strict ISO 8601 parsing (moment.ISO_8601, true) instead of moment's lenient auto-detection, eliminating the js Date() fallback that could behave inconsistently across environments
1.2.0
- New:
convertEpochToTimezone — format epoch in any IANA timezone
- New:
parseToEpoch — parse date strings to epoch with strict, timezone-aware parsing
- New:
getDurationBetween — calendar-accurate duration between two epochs
- New:
getTimezoneOffset — get UTC offset (DST-aware) for any IANA timezone
- New:
getTimezoneList — list all supported IANA timezone names
- New:
getEpochNow — current time as seconds, milliseconds, ISO string, and timezone
- New:
formatDuration — format a duration in ms as a human-readable string
- New:
isValidEpoch / isValidTimezone — safe boolean predicates (never throw)
- New types:
ParsedDuration, EpochNow, TimezoneOffset, DurationUnit, StartEndUnit
- New exports:
EpochUnit enum, EpochError enum, EpochValidationError class
- Fix:
validateEpoch no longer crashes on Infinity, -Infinity, NaN, or whitespace-only strings
- Fix: Empty-string check now trims whitespace before checking length
- Deps: Removed redundant
@types/moment; moved typescript and @types/node to devDependencies; updated moment-timezone to ^0.5.46 and typescript to ^5.8.3
1.1.1 and earlier
Initial release — convertEpoch and convertDateToEpoch.
Contributing
Issues and PRs are welcome at github.com/Master4Novice/temporal-transformer. The companion codemod lives at github.com/Master4Novice/temporal-transformer-codemod.
Credits
Written by Master4Novice.
License
MIT © Master4Novice