{"id":47825561,"url":"https://github.com/burglekitt/gmt","last_synced_at":"2026-05-16T14:01:18.245Z","repository":{"id":345109210,"uuid":"1177624369","full_name":"burglekitt/gmt","owner":"burglekitt","description":"Give Me Temporal! A long-due library to squash date and time bugs for good","archived":false,"fork":false,"pushed_at":"2026-05-10T11:50:02.000Z","size":649,"stargazers_count":4,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-10T13:30:15.620Z","etag":null,"topics":["biome","eslint","iso-8601","no-date","oxlint","tanstack-intent","temporal"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/burglekitt.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":"AGENTS.md","dco":null,"cla":null}},"created_at":"2026-03-10T07:54:12.000Z","updated_at":"2026-05-10T11:45:13.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/burglekitt/gmt","commit_stats":null,"previous_names":["burglekitt/gmt"],"tags_count":12,"template":false,"template_full_name":null,"purl":"pkg:github/burglekitt/gmt","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burglekitt%2Fgmt","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burglekitt%2Fgmt/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burglekitt%2Fgmt/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burglekitt%2Fgmt/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/burglekitt","download_url":"https://codeload.github.com/burglekitt/gmt/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/burglekitt%2Fgmt/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33105712,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-16T04:41:52.686Z","status":"ssl_error","status_checked_at":"2026-05-16T04:41:52.009Z","response_time":115,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["biome","eslint","iso-8601","no-date","oxlint","tanstack-intent","temporal"],"created_at":"2026-04-03T19:38:24.273Z","updated_at":"2026-05-16T14:01:18.238Z","avatar_url":"https://github.com/burglekitt.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# GMT: Give Me Temporal!\n\nHome of [@burglekitt/gmt](./packages/gmt) — **Give Me Temporal!**\n\nA monorepo for Burglekitt community libraries, built with Nx, powered by pnpm, and dead serious about making JavaScript date handling not terrible.\n\n## Install\n\nInstall the runtime package:\n\n```bash\npnpm add @burglekitt/gmt\n```\n\nQuick example:\n\n```js\nimport { getNow } from \"@burglekitt/gmt\";\nconsole.log(getNow()); // ISO 8601 string\n```\n\n## Aint Nobody Got Time For JavaScript Date objects\n\n![Aint nobody got time for that](https://media.giphy.com/media/bWM2eWYfN3r20/giphy.gif)\n\nWe do not use JavaScript `Date` APIs in this monorepo.\n\n- Aint nobody got time for `new Date()` mutability and environment drift.\n- Aint nobody got time for `Date.parse()` guessing what you meant.\n- Aint nobody got time for `Date.UTC()` argument gymnastics.\n- Aint nobody got time for `Date.now()` scattered magic numbers.\n\nUse GMT instead:\n\n- `getNow()`, `getUnixNow()`, and `getUtcNow()` for current time values.\n- `convertUtcDateTimeToUnix()` and `convertUtcToUnix()` for explicit unix conversion.\n- `convertTimezoneToUtc()` and `convertUtcToTimezone()` for timezone-safe conversion.\n- String-in/string-out APIs with Temporal under the hood for safer behavior.\n\nIf you see a Date API in code, replace it with a GMT helper.\n\n## Packages\n\n| Package | npm | Description |\n|---|---|---|\n| [`@burglekitt/gmt`](./packages/gmt) | `npm install @burglekitt/gmt` | Give Me Temporal — string-in/string-out date library |\n\n`@burglekitt/gmt` currently exports top-level `Temporal`, `plain`, `zoned`, `unix`, `utc`, and `regex` namespaces, with direct subpath imports available under `@burglekitt/gmt/*`.\n\n## Optional: Add Linting for Date API Bans\n\nWant to ban `Date` APIs in your own project? GMT provides linting packages:\n\n| Package | npm | Description |\n|---|---|---|\n| [`@burglekitt/gmt-biome`](./packages/gmt-biome) | `npm install -D @burglekitt/gmt-biome` | Shared Biome config — bans `Date` APIs via Grit plugins ([docs](./packages/gmt-biome/README.md)) |\n| [`@burglekitt/gmt-eslint`](./packages/gmt-eslint) | `npm install -D @burglekitt/gmt-eslint` | Shared ESLint flat config — bans `Date` APIs ([docs](./packages/gmt-eslint/README.md)) |\n| [`@burglekitt/gmt-oxlint`](./packages/gmt-oxlint) | `npm install -D @burglekitt/gmt-oxlint oxlint` | Shared Oxlint JS plugin — bans `Date` APIs ([docs](./packages/gmt-oxlint/README.md)) |\n\n---\n\n## Contributing\n\nQuick start for contributors:\n\n```bash\n# Install all workspace dependencies\npnpm install\n\n# Run tests across all packages\npnpm -w exec nx run-many -t test\n\n# Build all packages\npnpm -w exec nx run-many -t build\n\n# Lint and format\npnpm run lint\npnpm run format\n```\n\n### Project Structure\n\n```\n.\n├── packages/\n│   ├── gmt/                    # @burglekitt/gmt — Give Me Temporal!\n│   │   ├── src/\n│   │   │   ├── plain/          # Timezone-free operations\n│   │   │   │   ├── calculate/  # addDate, diffDateTime, subtractTime, ...\n│   │   │   │   ├── compare/    # isAfterDate, isBeforeDate, areDatesEqual, ...\n│   │   │   │   ├── format/     # formatDate, formatTime, formatDateTime, formatRelativeDate, ...\n│   │   │   │   ├── get/        # getNow, getToday, getUnixNow, ...\n│   │   │   │   ├── map/        # mapDaysInMonth, mapDatesInRange, ...\n│   │   │   │   ├── parse/      # parseDateUnit, parseTimeUnit, ...\n│   │   │   │   └── validate/   # isValidDate, unix validators, ...\n│   │   │   ├── zoned/          # IANA timezone-aware operations\n│   │   │   │   ├── calculate/  # addZoned, subtractZoned\n│   │   │   │   ├── compare/    # isAfterZoned, isBeforeZoned, areZonedEqual\n│   │   │   │   ├── convert/    # unix/utc/timezone conversion helpers\n│   │   │   │   ├── format/     # formatZonedDateTime, formatZonedRange, formatRelativeZoned\n│   │   │   │   ├── get/        # getZonedNow, getZonedToday, ...\n│   │   │   │   ├── map/        # mapZonedHoursInDay, mapZonedDatesInRange\n│   │   │   │   ├── parse/      # parseZonedDate, parseTimeFromZoned, ...\n│   │   │   │   └── validate/   # isValidZonedDateTime, isValidTimezone\n│   │   │   ├── unix/           # Unix epoch utilities\n│   │   │   │   ├── calculate/  # addUnix, subtractUnix, diffUnix, ...\n│   │   │   │   ├── convert/    # convertUnixToPlainDate, convertUnixToZoned, ...\n│   │   │   │   ├── format/     # formatUnix, formatRelativeUnix\n│   │   │   │   ├── get/        # getUnixNow, getUnixYear, ...\n│   │   │   │   ├── parse/      # parseDateFromUnix, parseTimeFromUnix, ...\n│   │   │   │   └── validate/   # isValidUnixSeconds, isValidUnixMilliseconds\n│   │   │   ├── utc/            # UTC instant utilities\n│   │   │   │   ├── calculate/  # addUtc, subtractUtc, diffUtc, ...\n│   │   │   │   ├── chop/       # chopUtc\n│   │   │   │   ├── convert/    # convertUtcToPlainDate, convertUtcToZoned, ...\n│   │   │   │   ├── format/     # formatUtc, formatRelativeUtc\n│   │   │   │   ├── get/        # getUtcNow, getUtcYear, ...\n│   │   │   │   ├── parse/      # parseDateFromUtc, parseTimeFromUtc, ...\n│   │   │   │   └── validate/   # isValidUtc\n│   │   │   ├── regex/          # Composable regex patterns for date/time strings\n│   │   │   └── package.json\n│   ├── gmt-biome/              # @burglekitt/gmt-biome — Shared Biome config\n│   │   ├── biome.json          # Consumer-facing config (uses ./plugins/ paths)\n│   │   └── plugins/            # Grit plugins banning Date APIs\n│   └── gmt-eslint/             # @burglekitt/gmt-eslint — Shared ESLint flat config\n│       └── eslint/\n│           └── index.mjs       # Flat config banning Date APIs\n├── burglekitt/                  # Nx workspace configuration (internal, do not publish)\n├── biome.json                   # Root Biome config — references gmt-biome plugins directly\n├── eslint.config.mjs            # Root ESLint config — imports gmt-eslint\n├── tsconfig.base.json           # Shared TypeScript base config\n└── package.json                 # Workspace root\n```\n\n### Workspace Scripts\n\nRun from the root:\n\n```bash\n# Test, build, typecheck\npnpm -w exec nx run-many -t test\npnpm -w exec nx run-many -t build\npnpm -w exec nx run-many -t typecheck\n\n# Code quality\npnpm run check\npnpm run lint\npnpm run format\n\n# Nx utilities\npnpm -w exec nx graph        # Visual dependency graph\npnpm -w exec nx sync         # Sync TypeScript project references\n```\n\n### Nx Commands You Will Actually Use\n\nAs more packages are added under `packages/*`, these commands become the default workflow:\n\n```bash\n# Run targets for every package\npnpm run build\npnpm run test:nx\npnpm run lint:nx\npnpm run typecheck\n\n# Full local gate before PR\npnpm run validate\n\n# Only run on projects affected by your branch changes\npnpm run affected:build\npnpm run affected:test\npnpm run affected:lint\npnpm run affected:typecheck\n\n# Workspace maintenance\npnpm run graph\npnpm run sync\npnpm run sync:check\npnpm run reset\n```\n\nRecommended PR flow:\n\n```bash\npnpm run affected:lint\npnpm run affected:test\npnpm run affected:typecheck\npnpm run affected:build\n```\n\nCI strategy:\n\n- Pull requests run `nx affected` targets (`lint`, `test`, `typecheck`, `build`) using `NX_BASE` and `NX_HEAD`.\n- Pushes to `main` run full `nx run-many` across all projects.\n- `defaultBase` is set to `main` in Nx config so local affected commands behave consistently.\n\nRun within a specific package:\n\n```bash\ncd packages/gmt\npnpm run test\npnpm run build\npnpm run lint\n```\n\n### Code Quality\n\n| Tool | Purpose |\n|---|---|\n| [Biome](https://biomejs.dev/) | Formatting and linting (+ Grit plugins for Date ban) |\n| [TypeScript](https://www.typescriptlang.org/) | Type safety |\n| [Vitest](https://vitest.dev/) | Testing |\n| [Nx](https://nx.dev/) | Task orchestration and caching |\n\nAll Biome rules are in [biome.json](./biome.json) (Grit plugins live in [packages/gmt-biome/plugins/](./packages/gmt-biome/plugins/)).\n\n### Releases\n\nPre-alpha. Each package follows semantic versioning and is published independently to npm.\n\n#### Publishing (manual)\n\nPublishing is manual only. We use [Changesets](https://github.com/changesets/changesets) to manage per-package versioning. Nothing publishes automatically — releases are triggered by maintainers.\n\nTwo supported publish paths:\n\n- **Local publish (recommended):** run Changesets locally with your npm credentials (passkey). This gives maintainers direct control and creates git tags when publishing.\n- **GitHub Actions (optional):** run the manual `Publish Package` workflow at `.github/workflows/publish.yml` via Actions → Run workflow. The workflow reads `NPM_TOKEN` from secrets and is gated by the `release` environment.\n\nPrerequisites for Actions-based publishing (optional):\n\n1. Create an npm access token with `Publish` permission for the `@burglekitt` org at https://www.npmjs.com/.\n2. Add it as a repository secret named `NPM_TOKEN` (or add it to the `release` environment) in GitHub (`Settings → Secrets` / `Settings → Environments`).\n\nBasic Changesets workflow:\n\n- On your feature branch, run `pnpm run changeset:add` to record the change and desired bump.\n- Merge the PR. If no `.changeset/*` files were merged, create changesets before versioning — Changesets only acts on files in `.changeset/`.\n- On `main`, run `pnpm run changeset:version` to apply version bumps and update changelogs; commit and push those changes.\n- To publish locally, run `pnpm run changeset:publish` from the repo root — this will publish packages and create package-scoped git tags.\n- If you use the Actions workflow to publish, run the workflow, then run `pnpm exec changeset tag` locally and `git push --follow-tags` to synchronize tags (Actions publish does not create tags).\n\nNotes:\n\n- Prefer using Changesets rather than manually bumping `package.json`; manual bumps can be used but they bypass the Changesets workflow.\n- Verify packages with `npm pack --dry-run` before publishing. For `@burglekitt/gmt`, run the dry-run after building.\n- The `Publish Package` workflow will build `@burglekitt/gmt` automatically when publishing that package.\n\nSee [PUBLISHING.md](./PUBLISHING.md) for the full, step-by-step guide and examples.\n\n---\n\n## License\n\nMIT — See [LICENSE](./LICENSE) for details.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fburglekitt%2Fgmt","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fburglekitt%2Fgmt","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fburglekitt%2Fgmt/lists"}