From 369ecc174c9c15c472f2ce38cb955ac135cb6b80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Mon, 31 Jul 2023 17:14:35 +0200 Subject: [PATCH 01/24] Document current date with no param --- utils/splitDateTime.ts | 3 +++ utils/splitLocalDateTime.ts | 3 +++ utils/splitUtcDateTime.ts | 2 ++ 3 files changed, 8 insertions(+) diff --git a/utils/splitDateTime.ts b/utils/splitDateTime.ts index 1515772..7ab3eaa 100644 --- a/utils/splitDateTime.ts +++ b/utils/splitDateTime.ts @@ -5,6 +5,9 @@ import { ComPlainTime, PlainTime } from "../PlainTime.ts"; * Get a function curried with a timezone, to split native JS `Date` objects * into separate plain-date and plain-time parts. * + * If called without `Date` parameter, the current date in the timezone will be + * returned. + * * @param timezone A named IANA timezone * @returns A curried function that operates on JS `Date` objects * diff --git a/utils/splitLocalDateTime.ts b/utils/splitLocalDateTime.ts index 07de0bd..5513d7a 100644 --- a/utils/splitLocalDateTime.ts +++ b/utils/splitLocalDateTime.ts @@ -4,6 +4,9 @@ import { ComPlainTime, PlainTime } from "../PlainTime.ts"; /** * Split native JS `Date` objects into separate plain-date and plain-time parts * in the system's local timezone. + * + * If called without `Date` parameter, the current date in the local timezone + * will be returned. */ export function splitLocalDateTime( instant?: Date, diff --git a/utils/splitUtcDateTime.ts b/utils/splitUtcDateTime.ts index 6a2174b..2369eb4 100644 --- a/utils/splitUtcDateTime.ts +++ b/utils/splitUtcDateTime.ts @@ -4,6 +4,8 @@ import { ComPlainTime, PlainTime } from "../PlainTime.ts"; /** * Split native JS `Date` objects into separate * plain-date and plain-time parts in UTC. + * + * If called without `Date` parameter, the current date in UTC will be returned. */ export function splitUtcDateTime(instant?: Date): [ComPlainDate, ComPlainTime] { instant ??= new Date(); From 714ba379d962b6dd94be0fd05aef4153132c6aff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Mon, 31 Jul 2023 18:07:09 +0200 Subject: [PATCH 02/24] Fix backticks in docblock --- PlainTime.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/PlainTime.ts b/PlainTime.ts index d1c4992..ee26ca3 100644 --- a/PlainTime.ts +++ b/PlainTime.ts @@ -94,7 +94,7 @@ export interface PlainTimeFactory { /** * Factory function for making basic plain-time objects with minimal properties. * - * @param time A time object with optional properties `hour`, `minute`, `second` & 'millisecond' + * @param time A time object with optional properties `hour`, `minute`, `second` & `millisecond` * @returns A new immutable plain-time object * * @throws {RangeError} Input total must be less than 24 hours From b1ec4165977bc1a8b1969624413b6fe9908bb58e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Mon, 7 Aug 2023 16:19:11 +0200 Subject: [PATCH 03/24] Document creating date and time objects --- README.md | 72 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 72 insertions(+) diff --git a/README.md b/README.md index 90004ac..ad78be7 100644 --- a/README.md +++ b/README.md @@ -116,6 +116,78 @@ will give the shortest of the formats `hh:mm` / `hh:mm:ss` / `hh:mm:ss.sss` depending on the resolution of the specific plain-time, but the `toLocaleString` method is best for controlled formatting in user interfaces. +## Creating date and time objects + +Pass any _calendar-date_ or _wall-time_ **shaped** objects to the factory +functions [`PlainDate`](https://deno.land/x/complaindate/mod.ts?s=PlainDate) and +[`PlainTime`](https://deno.land/x/complaindate/mod.ts?s=PlainTime): + +```ts +const someDate = PlainDate({ + year: 2023, + month: 7, + day: 31, +}); + +const someTime = PlainTime({ + hour: 13, + minute: 37, + second: 59, + millisecond: 999, +}); +``` + +Object properties may be numbers or strings and only `year` is required, the +others default to `1` for dates and `0` for times: + +```ts +const jan1 = PlainDate({ year: "2023" }); // 2023-01-01 +const midnight = PlainTime({}); // 00:00 +``` + +Functions +[`parsePlainDate`](https://deno.land/x/complaindate/mod.ts?s=parsePlainDate) and +[`parsePlainTime`](https://deno.land/x/complaindate/mod.ts?s=parsePlainTime) +creates objects from **strings**: + +```ts +const xMasDay = parsePlainDate("2023-12-25"); +const june1 = parsePlainDate("2023-06"); // 2023-06-01 + +const highResTime = parsePlainTime("01:02:03.004"); +const midday = parsePlainTime("12:00"); +``` + +If you have a JavaScript `Date` object, calling +[`splitDateTime`](https://deno.land/x/complaindate/mod.ts?s=splitDateTime) will +extract separate plain-date and plain-time objects for a given **timezone**: + +```ts +// Sweden is at UTC+2 in June, so this `Date` represents 13:37 wall-time there +const aJsDate = new Date("2023-06-06T13:37+0200"); + +const [june6, time1337] = splitDateTime("Europe/Stockholm")(aJsDate); +``` + +A `Date` can also be split in UTC using +[`splitUtcDateTime`](https://deno.land/x/complaindate/mod.ts?s=splitUtcDateTime) +or the system's timezone with +[`splitLocalDateTime`](https://deno.land/x/complaindate/mod.ts?s=splitLocalDateTime): + +```ts +const [june6, time1137] = splitUtcDateTime(aJsDate); +const [aSystemDate, aSystemTime] = splitLocalDateTime(aJsDate); +``` + +Leaving out the `Date` parameter for the split-functions will extract objects +representing **now**, the current date and current wall-time: + +```ts +const [todayInSweden, timeInSweden] = splitDateTime("Europe/Stockholm")(); +const [todayInUtc, timeInUtc] = splitUtcDateTime(); +const [todayInSystemTz, timeInSystemTz] = splitLocalDateTime(); +``` + ## Quick example This will show you how to split a native JavaScript `Date` into separate From fefb7d900874ccdc1d9c33f8673b4de4fe03fe88 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Mon, 7 Aug 2023 16:38:39 +0200 Subject: [PATCH 04/24] Document working with JS Date objects --- README.md | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/README.md b/README.md index ad78be7..3b5c5a1 100644 --- a/README.md +++ b/README.md @@ -330,6 +330,50 @@ name that is part of a longer string, use [`parseTimezone`](https://deno.land/x/complaindate/mod.ts?s=parseTimezone) directly to both sanitize and validate the result. +## Working with JavaScript `Date` objects + +JavaScript `Date` objects, that is _instants_, can be created from any date-time +**shaped** objects in a specified timezone: + +```ts +const noon2023Feb3InSweden = createInstant("Europe/Stockholm")({ + year: 2023, + month: 2, + day: 3, + hour: 12, + minute: 0, + second: 0, + millisecond: 0, +}); // 2023-02-03T11:00:00.000Z +``` + +These examples combine existing plain-date and plain-time objects: + +```ts +const jsDateInSweden = createInstant("Europe/Stockholm")({ + ...jan1, + ...midday, +}); // 2023-01-01T11:00:00.000Z + +const jsDateInSystemTz = createLocalInstant({ + ...jan1, + ...midday, +}); + +const jsDateInUtc = createUtcInstant({ + ...jan1, + ...midday, +}); // 2023-01-01T12:00:00.000Z +``` + +For UTC, that last example can also be written using the +[`toUtcInstant`](https://deno.land/x/complaindate/mod.ts?s=toUtcInstant) method +of the plain-date object, passing an optional wall-time shaped object: + +```ts +jan1.toUtcInstant(...midday); // 2023-01-01T12:00:00.000Z +``` + ## Why another JavaScript date-time library? Most other date-time libraries either don't provide any clear strategy for From 20ba2f58e5212797ca9cb240e40f8ed596bfa847 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Mon, 7 Aug 2023 16:38:49 +0200 Subject: [PATCH 05/24] Update TOC --- README.md | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 3b5c5a1..7d49db0 100644 --- a/README.md +++ b/README.md @@ -29,11 +29,13 @@ ComPlainDate is distributed as an **npm** package as well as a **Deno** module: ## Table of contents 1. [Introduction](#introduction) -2. [Quick example](#quick-example) -3. [Working with timezone strings](#working-with-timezone-strings) -4. [Why another JavaScript date-time library?](#why-another-javascript-date-time-library) -5. [Guiding principles](#guiding-principles) -6. [Limitations](#limitations) +2. [Creating date and time objects](#creating-date-and-time-objects) +3. [Quick example](#quick-example) +4. [Working with timezone strings](#working-with-timezone-strings) +5. [Working with JavaScript `Date` objects](#working-with-javascript-date-objects) +6. [Why another JavaScript date-time library?](#why-another-javascript-date-time-library) +7. [Guiding principles](#guiding-principles) +8. [Limitations](#limitations) ## Introduction From 6d75f82728583afb18d3ea91bbedb26c932d0732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Mon, 7 Aug 2023 20:05:11 +0200 Subject: [PATCH 06/24] Document new Date() --- README.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 7d49db0..6257caf 100644 --- a/README.md +++ b/README.md @@ -334,7 +334,13 @@ directly to both sanitize and validate the result. ## Working with JavaScript `Date` objects -JavaScript `Date` objects, that is _instants_, can be created from any date-time +JavaScript `Date` objects, that is _instants_, can of course be created in the +usual way using +[`new Date(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date) +with different arguments. It's perfect if you get a date-time as an ISO string, +like you usually do from a JSON API. + +With ComPlainDate `Date` objects can also be created from any date-time **shaped** objects in a specified timezone: ```ts From d7323bba694d00fb75d74142abee969343b97b6e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 12:23:52 +0200 Subject: [PATCH 07/24] Link to function docs --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 6257caf..89b924e 100644 --- a/README.md +++ b/README.md @@ -341,7 +341,11 @@ with different arguments. It's perfect if you get a date-time as an ISO string, like you usually do from a JSON API. With ComPlainDate `Date` objects can also be created from any date-time -**shaped** objects in a specified timezone: +**shaped** objects in a specified timezone with +[`createInstant`](https://deno.land/x/complaindate/mod.ts?s=createInstant), +[`createLocalInstant`](https://deno.land/x/complaindate/mod.ts?s=createLocalInstant) +and +[`createUtcInstant`](https://deno.land/x/complaindate/mod.ts?s=createUtcInstant): ```ts const noon2023Feb3InSweden = createInstant("Europe/Stockholm")({ From a8a524688be98fd914af1d84932ba17bc04c6db2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 12:24:29 +0200 Subject: [PATCH 08/24] Improve wording --- README.md | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 89b924e..2fcf5b0 100644 --- a/README.md +++ b/README.md @@ -334,11 +334,15 @@ directly to both sanitize and validate the result. ## Working with JavaScript `Date` objects -JavaScript `Date` objects, that is _instants_, can of course be created in the -usual way using -[`new Date(...)`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date) -with different arguments. It's perfect if you get a date-time as an ISO string, -like you usually do from a JSON API. +JavaScript `Date` objects, that is _instants_, can of course be created the +usual way with +[different arguments to the constructor](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date#parameters). +It's perfect when you have a date-time as an ISO string, like you usually get +from a JSON API. + +```ts +const instant = new Date(...); +``` With ComPlainDate `Date` objects can also be created from any date-time **shaped** objects in a specified timezone with From 0ce3238456172c7e089f47b0ea4064825ed39753 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 12:24:43 +0200 Subject: [PATCH 09/24] Add subheadings --- README.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/README.md b/README.md index 2fcf5b0..ca18cac 100644 --- a/README.md +++ b/README.md @@ -147,6 +147,8 @@ const jan1 = PlainDate({ year: "2023" }); // 2023-01-01 const midnight = PlainTime({}); // 00:00 ``` +### Extracting from strings + Functions [`parsePlainDate`](https://deno.land/x/complaindate/mod.ts?s=parsePlainDate) and [`parsePlainTime`](https://deno.land/x/complaindate/mod.ts?s=parsePlainTime) @@ -160,6 +162,8 @@ const highResTime = parsePlainTime("01:02:03.004"); const midday = parsePlainTime("12:00"); ``` +### Extracting from JavaScript `Date` objects + If you have a JavaScript `Date` object, calling [`splitDateTime`](https://deno.land/x/complaindate/mod.ts?s=splitDateTime) will extract separate plain-date and plain-time objects for a given **timezone**: From 0340ac990b9ded9254e05dd523104801e1a18139 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 12:24:59 +0200 Subject: [PATCH 10/24] Add comment --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index ca18cac..60a7f97 100644 --- a/README.md +++ b/README.md @@ -370,6 +370,7 @@ const noon2023Feb3InSweden = createInstant("Europe/Stockholm")({ These examples combine existing plain-date and plain-time objects: ```ts +// Sweden is at UTC+1 in January const jsDateInSweden = createInstant("Europe/Stockholm")({ ...jan1, ...midday, From 93c644e1bf8050d1a62e1eef77aa46ee8d43a67d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 12:26:46 +0200 Subject: [PATCH 11/24] Document working with Date objects --- README.md | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/README.md b/README.md index 60a7f97..65812d9 100644 --- a/README.md +++ b/README.md @@ -395,6 +395,35 @@ of the plain-date object, passing an optional wall-time shaped object: jan1.toUtcInstant(...midday); // 2023-01-01T12:00:00.000Z ``` +### Operations on `Date` objects + +Use functions [`addTime`](https://deno.land/x/complaindate/mod.ts?s=addTime) and +[`subtractTime`](https://deno.land/x/complaindate/mod.ts?s=subtractTime) to get +a new `Date` object shifted some **duration** from an existing one. Units up to +`hours` make sense here because an hour is exactly 60 minutes no matter what +timezone you're in. These methods just sum up the total milliseconds before +adjusting the given `Date` object. + +```ts +const jan1st1970 = new Date(0); // 1970-01-01T00:00:00.000Z + +const laterJsDate = addTime({ + hours: 25, + minutes: 61, + seconds: 61, + milliseconds: 1001, +})(jan1st1970); // 1970-01-02T02:02:02.001Z + +const earlierJsDate = subtractTime({ + hours: 1, + minutes: 1, +})(jan1st1970); // 1969-12-31T22:59:00.000Z +``` + +Adding `days` or larger duration units to a `Date` object must take timezones +into account and you should +[split that `Date` into plain-date and plain-time objects](#extracting-from-javascript-date-objects). + ## Why another JavaScript date-time library? Most other date-time libraries either don't provide any clear strategy for From ab1ffe3c4a841b679aa8bc5b6d435ad349697ae1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 12:59:19 +0200 Subject: [PATCH 12/24] Rename background section --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 65812d9..d36dac3 100644 --- a/README.md +++ b/README.md @@ -33,7 +33,7 @@ ComPlainDate is distributed as an **npm** package as well as a **Deno** module: 3. [Quick example](#quick-example) 4. [Working with timezone strings](#working-with-timezone-strings) 5. [Working with JavaScript `Date` objects](#working-with-javascript-date-objects) -6. [Why another JavaScript date-time library?](#why-another-javascript-date-time-library) +6. [Background](#background) 7. [Guiding principles](#guiding-principles) 8. [Limitations](#limitations) @@ -424,7 +424,7 @@ Adding `days` or larger duration units to a `Date` object must take timezones into account and you should [split that `Date` into plain-date and plain-time objects](#extracting-from-javascript-date-objects). -## Why another JavaScript date-time library? +## Background Most other date-time libraries either don't provide any clear strategy for timezone handling, for example [date-fns](https://date-fns.org), or keep the From bd91676031f8ee954f6c88c82d6476967ce7d31a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 13:32:39 +0200 Subject: [PATCH 13/24] Improve wording --- README.md | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index d36dac3..50121ab 100644 --- a/README.md +++ b/README.md @@ -88,9 +88,10 @@ time to reach for the other concepts, described below! ### `PlainDate` for _calendar dates_ -Plain-date objects adhere to a -[contract](https://deno.land/x/complaindate/mod.ts?s=ComPlainDate) and have -three numeric properties (`year`, `month`, and `day`) used for most operations. +Plain-date objects adhere to the +[`ComPlainDate` contract](https://deno.land/x/complaindate/mod.ts?s=ComPlainDate) +and have three numeric properties (`year`, `month`, and `day`) used for most +operations. The `iso` property and [string coercion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion) @@ -107,10 +108,11 @@ encouraged to build your own mapper functions on top of the existing ones. ### `PlainTime` for _time-of-day_ -Plain-time objects adhere to a -[contract](https://deno.land/x/complaindate/mod.ts?s=ComPlainTime) and have four -numeric properties (`hour`, `minute`, `second`, and `millisecond`), that may be -used for operations, but those are surprisingly uncommon. +Plain-time objects adhere to the +[`ComPlainTime` contract](https://deno.land/x/complaindate/mod.ts?s=ComPlainTime) +and have four numeric properties (`hour`, `minute`, `second`, and +`millisecond`), that may be used for operations, but those are surprisingly +uncommon. For display, [string coercion](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String#string_coercion) From 74c93a9cab6615bc09699d937497ba54db89152b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 13:35:14 +0200 Subject: [PATCH 14/24] Improve heading wording --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 50121ab..524a76e 100644 --- a/README.md +++ b/README.md @@ -149,7 +149,7 @@ const jan1 = PlainDate({ year: "2023" }); // 2023-01-01 const midnight = PlainTime({}); // 00:00 ``` -### Extracting from strings +### Extraction from strings Functions [`parsePlainDate`](https://deno.land/x/complaindate/mod.ts?s=parsePlainDate) and @@ -164,7 +164,7 @@ const highResTime = parsePlainTime("01:02:03.004"); const midday = parsePlainTime("12:00"); ``` -### Extracting from JavaScript `Date` objects +### Extraction from JavaScript `Date` objects If you have a JavaScript `Date` object, calling [`splitDateTime`](https://deno.land/x/complaindate/mod.ts?s=splitDateTime) will @@ -424,7 +424,7 @@ const earlierJsDate = subtractTime({ Adding `days` or larger duration units to a `Date` object must take timezones into account and you should -[split that `Date` into plain-date and plain-time objects](#extracting-from-javascript-date-objects). +[split that `Date` into plain-date and plain-time objects](#extraction-from-javascript-date-objects). ## Background From 37cfccdb432f731aa1ab4749b7d86a37ea2d55bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 14:29:58 +0200 Subject: [PATCH 15/24] Fix link --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 524a76e..0aaf435 100644 --- a/README.md +++ b/README.md @@ -390,8 +390,8 @@ const jsDateInUtc = createUtcInstant({ ``` For UTC, that last example can also be written using the -[`toUtcInstant`](https://deno.land/x/complaindate/mod.ts?s=toUtcInstant) method -of the plain-date object, passing an optional wall-time shaped object: +[`toUtcInstant`](https://deno.land/x/complaindate/mod.ts?s=ComPlainDate#prop_toUtcInstant) +method of the plain-date object, passing an optional wall-time shaped object: ```ts jan1.toUtcInstant(...midday); // 2023-01-01T12:00:00.000Z From b9c8cf4ebcbb23de958b515633d175f1eb53f1e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 14:40:23 +0200 Subject: [PATCH 16/24] Document formatInstant usage --- README.md | 28 +++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 0aaf435..9a928c3 100644 --- a/README.md +++ b/README.md @@ -397,7 +397,33 @@ method of the plain-date object, passing an optional wall-time shaped object: jan1.toUtcInstant(...midday); // 2023-01-01T12:00:00.000Z ``` -### Operations on `Date` objects +### Displaying a `Date` to users + +The [`formatInstant`](https://deno.land/x/complaindate/mod.ts?s=formatInstant) +utility generates formatting functions to reuse for consistency throughout a +user interface. It is curried in three rounds with a locale, format options, and +a timezone. Each parameter has a sensible default if left out, using the +system's locale and timezone, and including a short timezone name in the format. + +```ts +const formatDateTime = formatInstant()()(); // All defaults + +// Building a user specific formatter +const userLocale = "en-US"; +const userTimezone = "America/New_York"; +const format24hDateTimeForUser = formatInstant(userLocale)({ + hourCycle: "h23", +})(userTimezone); + +const aJsDate = new Date("2023-06-13T12:00Z"); + +// For a browser in Sweden: +formatDateTime(aJsDate); // "2023-06-13 14:00:00 CEST" + +format24hDateTimeForUser(aJsDate); // "6/13/2023, 08:00:00 EDT" +``` + +### Operations on `Date` Use functions [`addTime`](https://deno.land/x/complaindate/mod.ts?s=addTime) and [`subtractTime`](https://deno.land/x/complaindate/mod.ts?s=subtractTime) to get From bd9c3be5647139e411312b840a9a96aa2a199ad0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 14:42:43 +0200 Subject: [PATCH 17/24] Improve heading --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 9a928c3..ff5e73a 100644 --- a/README.md +++ b/README.md @@ -29,7 +29,7 @@ ComPlainDate is distributed as an **npm** package as well as a **Deno** module: ## Table of contents 1. [Introduction](#introduction) -2. [Creating date and time objects](#creating-date-and-time-objects) +2. [Creating plain-date and plain-time objects](#creating-plain-date-and-plain-time-objects) 3. [Quick example](#quick-example) 4. [Working with timezone strings](#working-with-timezone-strings) 5. [Working with JavaScript `Date` objects](#working-with-javascript-date-objects) @@ -120,7 +120,7 @@ will give the shortest of the formats `hh:mm` / `hh:mm:ss` / `hh:mm:ss.sss` depending on the resolution of the specific plain-time, but the `toLocaleString` method is best for controlled formatting in user interfaces. -## Creating date and time objects +## Creating plain-date and plain-time objects Pass any _calendar-date_ or _wall-time_ **shaped** objects to the factory functions [`PlainDate`](https://deno.land/x/complaindate/mod.ts?s=PlainDate) and From 24dc2ff1bda834f74b6b325f5bd7712a1eb0ce4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 14:54:43 +0200 Subject: [PATCH 18/24] Reduce comment clutter --- examples/quick-start.ts | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/examples/quick-start.ts b/examples/quick-start.ts index 2c50954..fd9608f 100644 --- a/examples/quick-start.ts +++ b/examples/quick-start.ts @@ -1,4 +1,3 @@ -// Deno users can import directly from deno.land, like this: import { addDays, createInstant, @@ -19,7 +18,7 @@ const [june6, time1337] = splitDateTime( )( // Sweden is at UTC+2 in June, so this `Date` represents 13:37 wall-time there new Date("2023-06-06T13:37+0200"), -); // Note: When called without a `Date`, this produces current wall-time (now) +); // The plain-date part is an object adhering to the full ComPlainDate interface june6; // { year: 2023, month: 6, day: 6, iso: "2023-06-06", ...} @@ -31,7 +30,6 @@ time1337; // { hour: 13, minute: 37, second: 0, millisecond: 0, ... } time1337.toLocaleString("en"); // "1:37 PM" // Apply any pipeline of operations to get a new plain-date -// ...free from any hassle involving timezones! const midsummersEve = june6.pipe( startOfMonth, // Go back to the 1st day of June addDays(18), // Move to the first possible midsummer's eve candidate (June 19) @@ -54,9 +52,8 @@ newYearsDay.toUtcInstant(); // 2023-01-01T00:00:00.000Z // Combine any shape of local date & time into an "instant", a JS `Date` createInstant( - // The Wiener Musikverein is at UTC+1 in January "Europe/Vienna", // Note: A timezone is required for this operation )({ ...newYearsDay, - ...{ hour: 11, minute: 15 }, + ...{ hour: 11, minute: 15 }, // The Wiener Musikverein is at UTC+1 in January }); // 2023-01-01T10:15:00.000Z From c95c3d703b2d0c896e69461e89771970ab0a7e4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 14:55:53 +0200 Subject: [PATCH 19/24] Paste updated quick example --- README.md | 21 ++------------------- 1 file changed, 2 insertions(+), 19 deletions(-) diff --git a/README.md b/README.md index ff5e73a..a9b40e7 100644 --- a/README.md +++ b/README.md @@ -209,28 +209,13 @@ The final step will merge a plain-date and a plain-time into a native JavaScript `Date`, completing the circle. ```ts -// Deno users can import directly from deno.land, like this: -import { - addDays, - createInstant, - daysInMonth, - differenceInMonths, - firstWeekDay, - isLastDayOfMonth, - splitDateTime, - startOfMonth, - startOfYear, - WeekDay, - weekDayNumber, -} from "https://deno.land/x/complaindate/mod.ts"; - // Extract a plain-date and a plain-time from any JS `Date` const [june6, time1337] = splitDateTime( "Europe/Stockholm", // Note: A timezone is required for this operation )( // Sweden is at UTC+2 in June, so this `Date` represents 13:37 wall-time there new Date("2023-06-06T13:37+0200"), -); // Note: When called without a `Date`, this produces current wall-time (now) +); // The plain-date part is an object adhering to the full ComPlainDate interface june6; // { year: 2023, month: 6, day: 6, iso: "2023-06-06", ...} @@ -242,7 +227,6 @@ time1337; // { hour: 13, minute: 37, second: 0, millisecond: 0, ... } time1337.toLocaleString("en"); // "1:37 PM" // Apply any pipeline of operations to get a new plain-date -// ...free from any hassle involving timezones! const midsummersEve = june6.pipe( startOfMonth, // Go back to the 1st day of June addDays(18), // Move to the first possible midsummer's eve candidate (June 19) @@ -265,11 +249,10 @@ newYearsDay.toUtcInstant(); // 2023-01-01T00:00:00.000Z // Combine any shape of local date & time into an "instant", a JS `Date` createInstant( - // The Wiener Musikverein is at UTC+1 in January "Europe/Vienna", // Note: A timezone is required for this operation )({ ...newYearsDay, - ...{ hour: 11, minute: 15 }, + ...{ hour: 11, minute: 15 }, // The Wiener Musikverein is at UTC+1 in January }); // 2023-01-01T10:15:00.000Z ``` From 72d2cdceefaa03ca6ddc2018289614f2f796b3b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 15:13:01 +0200 Subject: [PATCH 20/24] Remove temporary namespace extension Now included with TypeScript 5.1 --- utils/supportedCanonicalTimezones.ts | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/utils/supportedCanonicalTimezones.ts b/utils/supportedCanonicalTimezones.ts index 9ba1c6c..18c20ba 100644 --- a/utils/supportedCanonicalTimezones.ts +++ b/utils/supportedCanonicalTimezones.ts @@ -1,22 +1,3 @@ -/** - * Intl.supportedValuesOf is not shipped until Typescript 5.1 - * Temporary workaround is from - * https://github.com/microsoft/TypeScript/issues/49231#issuecomment-1137251612 - * - * TODO: When Typescript 5.1 is released with Deno (check with `deno --version`), remove this namespace extension. - */ -declare namespace Intl { - type Key = - | "calendar" - | "collation" - | "currency" - | "numberingSystem" - | "timeZone" - | "unit"; - - function supportedValuesOf(input: Key): string[]; -} - /** * Get all canonical timezones that are supported by the browser or runtime, * or an empty array if the list is not available. From 721b54019d09ac1a0032b84bb80658ead0e86c13 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 15:17:19 +0200 Subject: [PATCH 21/24] Remove toUtcInstant call from quick example ...because this is mentioned in other docs now --- README.md | 3 --- examples/quick-start.ts | 3 --- 2 files changed, 6 deletions(-) diff --git a/README.md b/README.md index a9b40e7..e298b16 100644 --- a/README.md +++ b/README.md @@ -244,9 +244,6 @@ isLastDayOfMonth(newYearsDay); // false weekDayNumber(midsummersEve); // 5 (equal to `WeekDay.FRIDAY`) differenceInMonths(midsummersEve)(newYearsDay); // -5 -// Quickly turn a plain-date into a UTC "instant", a JS `Date` at UTC midnight -newYearsDay.toUtcInstant(); // 2023-01-01T00:00:00.000Z - // Combine any shape of local date & time into an "instant", a JS `Date` createInstant( "Europe/Vienna", // Note: A timezone is required for this operation diff --git a/examples/quick-start.ts b/examples/quick-start.ts index fd9608f..2840ac5 100644 --- a/examples/quick-start.ts +++ b/examples/quick-start.ts @@ -47,9 +47,6 @@ isLastDayOfMonth(newYearsDay); // false weekDayNumber(midsummersEve); // 5 (equal to `WeekDay.FRIDAY`) differenceInMonths(midsummersEve)(newYearsDay); // -5 -// Quickly turn a plain-date into a UTC "instant", a JS `Date` at UTC midnight -newYearsDay.toUtcInstant(); // 2023-01-01T00:00:00.000Z - // Combine any shape of local date & time into an "instant", a JS `Date` createInstant( "Europe/Vienna", // Note: A timezone is required for this operation From fd1d2a6a54530622b6cc6ede223f290291df800e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 15:18:33 +0200 Subject: [PATCH 22/24] Improve wording --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index e298b16..2891e9e 100644 --- a/README.md +++ b/README.md @@ -280,10 +280,10 @@ Because the timezone used may be a fallback and not what the user expects, it's important to _always_ display the actual timezone name whenever time information is present in the user interface. -[`formatTimezone`](https://deno.land/x/complaindate/mod.ts?s=formatTimezone) -will make a timezone name look pretty for the user. It replaces underscores with -spaces to give a less technical impression, for example `"Africa/Dar es Salaam"` -instead of `"Africa/Dar_es_Salaam"`. +The [`formatTimezone`](https://deno.land/x/complaindate/mod.ts?s=formatTimezone) +utility will make a timezone name look pretty for the user. It replaces +underscores with spaces to give a less technical impression, for example +`"Africa/Dar es Salaam"` instead of `"Africa/Dar_es_Salaam"`. ### Guided timezone preference input From 81c8f4dcf7bd9b6b1e379cb7610fb0d9c77588ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 15:21:14 +0200 Subject: [PATCH 23/24] Improve comment placement --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 2891e9e..99b4dfb 100644 --- a/README.md +++ b/README.md @@ -352,10 +352,9 @@ const noon2023Feb3InSweden = createInstant("Europe/Stockholm")({ These examples combine existing plain-date and plain-time objects: ```ts -// Sweden is at UTC+1 in January const jsDateInSweden = createInstant("Europe/Stockholm")({ ...jan1, - ...midday, + ...midday, // Sweden is at UTC+1 in January }); // 2023-01-01T11:00:00.000Z const jsDateInSystemTz = createLocalInstant({ From a7ae5c703c277e30a42735033f972015e323a34f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Nilsved?= Date: Tue, 8 Aug 2023 16:29:32 +0200 Subject: [PATCH 24/24] Improve API docs wording --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 99b4dfb..0604203 100644 --- a/README.md +++ b/README.md @@ -16,8 +16,10 @@ available — only time will tell… ## API documentation -The full [API documentation](https://deno.land/x/complaindate/mod.ts) and -categorized lists of available functions are available at deno.land. +The detailed documentation and categorized lists of available functions are +available at the _deno.land_ website. +[The API documentation](https://deno.land/x/complaindate/mod.ts) is where you'll +find what utilities will help you solve your specific problem. ## Installation