Skip to content

Commit

Permalink
feat: js-joda support (#589)
Browse files Browse the repository at this point in the history
* add js-joda to date-io

* Hanlde Errors passed to date()

* Make parser smarter. Handle LocalDate and LocalDateTime

* All Temporal are valid

* Normalize to LocalDateTime

* use "day of month" not "day of Year" for tests

* add deps for ru locale

* add localization and format tests for js-joda

* add a test start of week on a sunday to cover non iso weeks

* add ZonedDateTime to calendar type

* Simplify conditionals for coverage test

* Use optional Parser to allow LocalDate as well as LocalDateTime. and add test coverage to that

* check format for "a" to decide if 12 hour cycle

* simplify isSameDay logic

* fix issues with the default formats

* allow a LocalDate to be parsed

* Remove unusable ChronoUnit

* Use Year isBefore instead of js-joda-utils
  • Loading branch information
dspiteself authored Oct 4, 2021
1 parent 0466222 commit c694d02
Show file tree
Hide file tree
Showing 15 changed files with 1,284 additions and 12 deletions.
13 changes: 13 additions & 0 deletions __tests__/calculations.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,19 @@ describe("DateTime calculations", () => {
);
});

utilsTest("startOfWeekNonISO", (date, utils, lib) => {
expect(utils.formatByString(utils.startOfWeek(utils.date("2018-10-28T00:00:00.000Z")), formats.dateTime[lib])).toBe(
lib === "Luxon" ? "2018-10-22 00:00" : "2018-10-28 00:00"
);
});

utilsTest("endOfWeekNonISO", (date, utils, lib) => {
expect(utils.formatByString(utils.endOfWeek(utils.date("2018-10-28T00:00:00.000Z")), formats.dateTime[lib])).toBe(
lib === "Luxon" ? "2018-10-28 23:59" : "2018-11-03 23:59"
);
});


utilsTest("getPreviousMonth", (date, utils, lib) => {
expect(
utils.formatByString(utils.getPreviousMonth(date), formats.dateTime[lib])
Expand Down
55 changes: 55 additions & 0 deletions __tests__/formats.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@ import LuxonUtils from "../packages/luxon/src";
import DateFnsUtils from "../packages/date-fns/src";
import MomentUtils from "../packages/moment/src";
import DayjsUtils from "../packages/dayjs/src";
import JsJodaUtils from "../packages/js-joda/src";
import { allUtils } from "./test-utils";
import moment from "moment";
import "dayjs/locale/ru";
import {
Locale
} from "@js-joda/locale";
import {DateIOFormats} from "@date-io/core/IUtils";

test.each`
format | expectedWithEn
Expand Down Expand Up @@ -116,4 +121,54 @@ describe("Localized formats", () => {
expect(luxonUtils.format(date, format)).toBe(expectedWithEn);
expect(luxonRuUtils.format(date, format)).toBe(expectedWithRu);
});
test.each`
format | expectedWithEn | expectedWithRu
${"fullDate"} | ${"Feb 1, 2020"} | ${"1 февр. 2020 г."}
${"fullDateWithWeekday"} | ${"Saturday, February 1, 2020"} | ${"суббота, 1 февраля 2020 г."}
${"fullDateTime"} | ${"Feb 1, 2020 11:44 PM"} | ${"1 февр. 2020 г., 23:44"}
${"fullDateTime12h"} | ${"Feb 1, 2020 11:44 PM"} | ${"1 февр. 2020 г., 11:44 PM"}
${"fullDateTime24h"} | ${"Feb 1, 2020 23:44"} | ${"1 февр. 2020 г., 23:44"}
${"keyboardDate"} | ${"02/01/2020"} | ${"01.02.2020"}
${"keyboardDateTime"} | ${"02/01/2020 11:44 PM"} | ${"01.02.2020 23:44"}
${"keyboardDateTime12h"} | ${"02/01/2020 11:44 PM"} | ${"01.02.2020 11:44 PM"}
${"keyboardDateTime24h"} | ${"02/01/2020 23:44"} | ${"01.02.2020 23:44"}
`("JsJoda localized $format", ({ format, expectedWithEn, expectedWithRu }) => {
const russianFormats: DateIOFormats = {
dayOfMonth: "d",
fullDate: "d LLL yyyy 'г.'",
fullDateWithWeekday: "EEEE, d LLLL yyyy 'г.'",
fullDateTime: "d LLL yyyy 'г.', HH:mm",
fullDateTime12h: "d LLL yyyy 'г.', hh:mm a",
fullDateTime24h: "d LLL yyyy 'г.', HH:mm",
fullTime: "",
fullTime12h: "hh:mm a",
fullTime24h: "HH:mm",
hours12h: "hh",
hours24h: "HH",
keyboardDate: "dd.MM.yyyy",
keyboardDateTime: "dd.MM.yyyy HH:mm",
keyboardDateTime12h: "dd.MM.yyyy hh:mm a",
keyboardDateTime24h: "dd.MM.yyyy HH:mm",
minutes: "mm",
month: "LLLL",
monthAndDate: "LLLL d",
monthAndYear: "LLLL yyyy",
monthShort: "LLL",
weekday: "EEEE",
weekdayShort: "EEE",
normalDate: "d MMMM",
normalDateWithWeekday: "EEE, MMM d",
seconds: "ss",
shortDate: "MMM d",
year: "yyyy",
};
const jsJodaEnUtils = new JsJodaUtils({});
const jsJodaRuUtils = new JsJodaUtils(
{locale: new Locale("ru"),
formats : russianFormats});
const date = jsJodaEnUtils.date("2020-02-01T23:44:00.000Z");

expect(jsJodaEnUtils.format(date, format)).toBe(expectedWithEn);
expect(jsJodaRuUtils.format(date, format)).toBe(expectedWithRu);
});
});
299 changes: 299 additions & 0 deletions __tests__/local-date-calculations.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,299 @@
import { localDateutilsTest, formats, LOCALDATE_TEST_TIMESTAMP } from "./test-utils";

describe("DateTime calculations", () => {
localDateutilsTest("date", (date, utils) => {
// ISO string
expect(utils.isEqual(date, utils.date(LOCALDATE_TEST_TIMESTAMP))).toBeTruthy();
// parse already date-specific object
expect(utils.isEqual(date, utils.date(utils.date(LOCALDATE_TEST_TIMESTAMP)))).toBeTruthy();
// parse null inputs
expect(utils.date(null)).toBeNull();
// undefined
expect(utils.date(undefined)).toBeTruthy();
});

localDateutilsTest("isValid", (date, utils) => {
const invalidDate = utils.date("2018-42-30T11:60:00.000Z");

expect(utils.isValid(date)).toBeTruthy();
expect(utils.isValid(invalidDate)).toBeFalsy();
expect(utils.isValid(undefined)).toBeTruthy();
expect(utils.isValid(null)).toBeFalsy();
expect(utils.isValid("2018-42-30T11:60:00.000Z")).toBeFalsy();
});

localDateutilsTest("addDays", (date, utils, lib) => {
expect(utils.format(utils.addDays(date, 1), "dayOfMonth")).toBe("31");
expect(utils.format(utils.addDays(date, -1), "dayOfMonth")).toBe("29");
});

localDateutilsTest("addWeeks", (date, utils, lib) => {
expect(utils.getDiff(utils.addWeeks(date, 1), date, "weeks")).toBe(1);
expect(utils.getDiff(utils.addWeeks(date, -1), date, "weeks")).toBe(-1);
});

localDateutilsTest("addMonths", (date, utils, lib) => {
expect(utils.format(utils.addMonths(date, 2), "monthAndYear")).toBe("December 2018");
expect(utils.format(utils.addMonths(date, -2), "monthAndYear")).toBe("August 2018");
});

localDateutilsTest("startOfDay", (date, utils, lib) => {
expect(utils.formatByString(utils.startOfDay(date), formats.dateTime[lib])).toBe(
"2018-10-30 00:00"
);
});

localDateutilsTest("endOfDay", (date, utils, lib) => {
expect(utils.formatByString(utils.endOfDay(date), formats.dateTime[lib])).toBe(
"2018-10-30 23:59"
);
});

localDateutilsTest("startOfMonth", (date, utils, lib) => {
expect(utils.formatByString(utils.startOfMonth(date), formats.dateTime[lib])).toBe(
"2018-10-01 00:00"
);
});

localDateutilsTest("endOfMonth", (date, utils, lib) => {
expect(utils.formatByString(utils.endOfMonth(date), formats.dateTime[lib])).toBe(
"2018-10-31 23:59"
);
});

localDateutilsTest("startOfWeek", (date, utils, lib) => {
expect(utils.formatByString(utils.startOfWeek(date), formats.dateTime[lib])).toBe(
lib === "Luxon" ? "2018-10-29 00:00" : "2018-10-28 00:00"
);
});

localDateutilsTest("endOfWeek", (date, utils, lib) => {
expect(utils.formatByString(utils.endOfWeek(date), formats.dateTime[lib])).toBe(
lib === "Luxon" ? "2018-11-04 23:59" : "2018-11-03 23:59"
);
});

localDateutilsTest("getPreviousMonth", (date, utils, lib) => {
expect(
utils.formatByString(utils.getPreviousMonth(date), formats.date[lib])
).toBe("2018-09-30");
});

localDateutilsTest("getMonthArray", (date, utils, lib) => {
expect(
utils
.getMonthArray(date)
.map((date) => utils.formatByString(date, formats.dateTime[lib]))
).toEqual([
"2018-01-01 00:00",
"2018-02-01 00:00",
"2018-03-01 00:00",
"2018-04-01 00:00",
"2018-05-01 00:00",
"2018-06-01 00:00",
"2018-07-01 00:00",
"2018-08-01 00:00",
"2018-09-01 00:00",
"2018-10-01 00:00",
"2018-11-01 00:00",
"2018-12-01 00:00",
]);
});

localDateutilsTest("getNextMonth", (date, utils, lib) => {
expect(utils.formatByString(utils.getNextMonth(date), formats.date[lib])).toBe(
"2018-11-30"
);
});


localDateutilsTest("getYear", (date, utils) => {
expect(utils.getYear(date)).toBe(2018);
});

localDateutilsTest("getMonth", (date, utils) => {
expect(utils.getMonth(date)).toBe(9);
});

localDateutilsTest("getDaysInMonth", (date, utils) => {
expect(utils.getDaysInMonth(date)).toBe(31);
});

localDateutilsTest("setMonth", (date, utils, lib) => {
const updatedTime = utils.formatByString(
utils.setMonth(date, 4),
formats.date[lib]
);
expect(updatedTime).toBe("2018-05-30");
});

localDateutilsTest("setYear", (date, utils, lib) => {
const updatedTime = utils.formatByString(
utils.setYear(date, 2011),
formats.date[lib]
);
expect(updatedTime).toBe("2011-10-30");
});

localDateutilsTest("isAfter", (date, utils, lib) => {
expect(utils.isAfter(utils.date("2021-01-01"), utils.date(LOCALDATE_TEST_TIMESTAMP))).toBeTruthy();
expect(utils.isAfter(utils.date(LOCALDATE_TEST_TIMESTAMP), utils.date("2021-01-01"))).toBeFalsy();
});

localDateutilsTest("isBefore", (date, utils, lib) => {
expect(utils.isBefore(utils.date(LOCALDATE_TEST_TIMESTAMP), utils.date("2021-01-01"))).toBeTruthy();
expect(utils.isBefore(utils.date("2021-01-01"), utils.date(LOCALDATE_TEST_TIMESTAMP))).toBeFalsy();
});

localDateutilsTest("isAfterDay", (date, utils, lib) => {
const nextDay = utils.addDays(date, 1);

expect(utils.isAfterDay(nextDay, date)).toBeTruthy();
expect(utils.isAfterDay(date, nextDay)).toBeFalsy();
});

localDateutilsTest("isBeforeDay", (date, utils, lib) => {
const previousDay = utils.addDays(date, -1);

expect(utils.isBeforeDay(date, previousDay)).toBeFalsy();
expect(utils.isBeforeDay(previousDay, date)).toBeTruthy();
});

localDateutilsTest("isAfterYear", (date, utils, lib) => {
const nextYear = utils.setYear(date, 2019);

expect(utils.isAfterYear(nextYear, date)).toBeTruthy();
expect(utils.isAfterYear(date, nextYear)).toBeFalsy();
});

localDateutilsTest("isBeforeYear", (date, utils, lib) => {
const previousYear = utils.setYear(date, 2017);

expect(utils.isBeforeYear(date, previousYear)).toBeFalsy();
expect(utils.isBeforeYear(previousYear, date)).toBeTruthy();
});

localDateutilsTest("getWeekArray", (date, utils) => {
const weekArray = utils.getWeekArray(date);

expect(weekArray).toHaveLength(5);
for (const week of weekArray) {
expect(week).toHaveLength(7);
}
});

localDateutilsTest("getYearRange", (date, utils) => {
const yearRange = utils.getYearRange(date, utils.setYear(date, 2124));

expect(yearRange).toHaveLength(107);
expect(utils.getYear(yearRange[yearRange.length - 1])).toBe(2124);

const emptyYearRange = utils.getYearRange(
date,
utils.setYear(date, utils.getYear(date) - 1)
);

expect(emptyYearRange).toHaveLength(0);
});


localDateutilsTest("getDiff with units", (date, utils) => {
expect(utils.getDiff(date, utils.date("2017-09-29"), "years")).toBe(1);
expect(utils.getDiff(date, utils.date("2018-08-29"), "months")).toBe(2);
expect(utils.getDiff(date, utils.date("2018-05-29"), "quarters")).toBe(
1
);
expect(utils.getDiff(date, utils.date("2018-09-29"), "days")).toBe(31);
expect(utils.getDiff(date, utils.date("2018-09-29"), "weeks")).toBe(4);
});

localDateutilsTest("mergeDateAndTime", (date, utils, lib) => {
const mergedDate = utils.mergeDateAndTime(
date,
utils.date("2018-01-01T14:15:16.000Z")
);

expect(utils.toJsDate(mergedDate).toISOString()).toBe("2018-10-30T14:15:16.000Z");
});

localDateutilsTest("isEqual", (date, utils) => {
expect(utils.isEqual(utils.date(null), null)).toBeTruthy();
expect(utils.isEqual(date, utils.date(LOCALDATE_TEST_TIMESTAMP))).toBeTruthy();
expect(utils.isEqual(null, utils.date(LOCALDATE_TEST_TIMESTAMP))).toBeFalsy();
});

localDateutilsTest("parse", (date, utils, lib) => {
const parsedDate = utils.parse("2018-10-30", formats.date[lib]);

expect(utils.isEqual(parsedDate, date)).toBeTruthy();
expect(utils.parse("", formats.dateTime[lib])).toBeNull();
});

localDateutilsTest("parse invalid inputs", (date, utils, lib) => {
const parsedDate = utils.parse("99-99-9999", formats.dateTime[lib]);

// expect(utils.isValid(parsedDateMoreText)).toBe(false);
expect(utils.isValid(parsedDate)).toBe(false);
});

localDateutilsTest("isNull", (date, utils, lib) => {
expect(utils.isNull(null)).toBeTruthy();
expect(utils.isNull(date)).toBeFalsy();
});

localDateutilsTest("isSameDay", (date, utils, lib) => {
expect(utils.isSameDay(date, utils.date("2018-10-30T00:00:00.000Z"))).toBeTruthy();
expect(utils.isSameDay(date, utils.date("2019-10-30T00:00:00.000Z"))).toBeFalsy();
});

localDateutilsTest("isSameMonth", (date, utils, lib) => {
expect(utils.isSameMonth(date, utils.date("2018-10-01T00:00:00.000Z"))).toBeTruthy();
expect(utils.isSameMonth(date, utils.date("2019-10-01T00:00:00.000Z"))).toBeFalsy();
});

localDateutilsTest("isSameYear", (date, utils, lib) => {
expect(utils.isSameYear(date, utils.date("2018-10-01T00:00:00.000Z"))).toBeTruthy();
expect(utils.isSameYear(date, utils.date("2019-10-01T00:00:00.000Z"))).toBeFalsy();
});


localDateutilsTest("getCurrentLocaleCode: returns default locale", (date, utils, lib) => {
expect(utils.getCurrentLocaleCode()).toMatch(/en/);
});

localDateutilsTest("toJsDate: returns date object", (date, utils) => {
expect(utils.toJsDate(date)).toBeInstanceOf(Date);
});

localDateutilsTest("isWithinRange: checks that dates isBetween 2 other dates", (date, utils) => {
expect(
utils.isWithinRange(utils.date("2019-10-01"), [
utils.date("2019-09-01"),
utils.date("2019-11-01"),
])
).toBeTruthy();

expect(
utils.isWithinRange(utils.date("2019-12-01"), [
utils.date("2019-09-01"),
utils.date("2019-11-01"),
])
).toBeFalsy();
});

localDateutilsTest("isWithinRange: should use inclusivity of range", (date, utils) => {
expect(
utils.isWithinRange(utils.date("2019-09-01"), [
utils.date("2019-09-01"),
utils.date("2019-12-01"),
])
).toBeTruthy();

expect(
utils.isWithinRange(utils.date("2019-12-01"), [
utils.date("2019-09-01"),
utils.date("2019-12-01"),
])
).toBeTruthy();
});
});
Loading

0 comments on commit c694d02

Please sign in to comment.