Hacktoberfest 2026: the issues maintainers tagged for October, open and beginner-friendly. Browse Hacktoberfest issues

DateTime: toDate reads formatToParts by position, breaks on Hermes Android (no fractionalSecond part)

Closed Beginner friendly
#8,689 0 comments 0 reactions 0 assignees View on GitHub

Maintainers usually reply within 1 day

@maricastroc is already working on this.

Since Oct 3, 2026.

  • #8692 by @maricastroc — open
  • #8707 by @tim-smart — merged

Assessment

Difficulty
2/5
Estimated time
1-3 hours
Newbie friendliness
84/100
Issue type
Bug
Clarity
Clearly specified
Activity status
Active
Tech stack
android, react-native, typescript
Domain
mobile-dev

Research direction

Start in internal/dateTime.ts at toDate, where the zone formatter's formatToParts output is read by position. Reproduce the failure with the supplied Node snippet, then verify that formatIsoDate returns the expected local date when fractionalSecond is absent, including on Hermes Android.

Written by the indexing model from the issue text.

Description

What version of Effect is running?

4.0.0 (also present on main)

What steps can reproduce the bug?

toDate in internal/dateTime.ts reads the zone formatter's formatToParts output by position: parts[0] is the month, parts[2] the year, through parts[6] for the fractional second. When the runtime's Intl leaves out a part, the indices shift and a later part, such as the time zone name, ends up in a numeric slot.

Hermes on Android does this. Its Java-backed Intl ignores fractionalSecondDigits, so no fractionalSecond part is emitted and parts[6] is the timeZoneName ("GMT+10:00"). Number("GMT+10:00") is NaN, the Date becomes invalid, and anything that formats it throws. In our React Native app, every DateTime.formatIsoDate on a zoned value threw on Android.

A Node repro that simulates the missing part:

import { DateTime } from "effect"

const formatToParts = Intl.DateTimeFormat.prototype.formatToParts
Intl.DateTimeFormat.prototype.formatToParts = function(date) {
  return formatToParts.call(this, date).filter((part) => part.type !== "fractionalSecond")
}

const zoned = DateTime.makeZonedUnsafe(new Date(), { timeZone: DateTime.zoneMakeLocal() })
DateTime.formatIsoDate(zoned)
What is the expected behavior?

"2026-10-03", or whatever the local date is.

What do you see instead?

RangeError: Invalid time value in Node. Hermes reports the same failure as RangeError: Date value out of bounds.

Additional information

Reading the parts by type fixes it, and falling back to the epoch's own milliseconds when fractionalSecond is absent is exact for any zone with a whole-second offset:

const parts: Partial<Record<Intl.DateTimeFormatPartTypes, string>> = {}
for (const part of self.zone.format.formatToParts(self.epochMilliseconds)) {
  parts[part.type] = part.value
}
const date = new Date(0)
date.setUTCFullYear(Number(parts.year), Number(parts.month) - 1, Number(parts.day))
date.setUTCHours(
  Number(parts.hour),
  Number(parts.minute),
  Number(parts.second),
  parts.fractionalSecond === undefined
    ? self.epochMilliseconds - Math.floor(self.epochMilliseconds / 1000) * 1000
    : Number(parts.fractionalSecond)
)

Hermes's Android Intl: lib/Platform/Intl/java/com/facebook/hermes/intl in facebook/hermes has no fractionalSecondDigits handling.

Dominant language
TypeScript
Stars
16.7k
Forks
808
Avg merge
10h 7m
Merged PRs (30d)
441

Getting set up

This project ships no dev container, Dockerfile or contributing guide, so setting up is up to you: start from its README, and see our first-contribution guide for the general steps.

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from Effect-TS/effect

All issues in Effect-TS/effect

Similar issues

More TypeScript issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.