Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions homedocs/src/pages/docs/intro/formatting.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,15 @@ Date and time patterns can be combined: `d;yyyyMMddHHmm` formats both date and t

For more details on culture-sensitive formatting, see [intl-io](https://github.com/codaxy/intl-io).

### Day-Before Format

The `daybefore` format renders a date shifted back by one calendar day. It accepts the same pattern argument as `datetime`, which makes it convenient for displaying the *exclusive* end of a date range as an inclusive value — for example, a period running from `2020-01-01` up to (but not including) `2021-01-01` can be shown as `Dec 2020`.

| Format | Example Input | Example Output |
| -------------------- | ------------- | -------------- |
| `daybefore;MMM yyyy` | `2021-01-01` | `Dec 2020` |
| `daybefore;yyyyMMdd` | `2021-01-01` | `12/31/2020` |

## Programmatic Formatting

Use `Format.value()` to format values in code:
Expand Down
8 changes: 7 additions & 1 deletion packages/cx/src/ui/Format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import { Culture, getCurrentCultureCache } from "./Culture";
import { Format as Fmt, resolveMinMaxFractionDigits, setGetFormatCacheCallback } from "../util/Format";
import { setGetExpressionCacheCallback } from "../data/Expression";
import { setGetStringTemplateCacheCallback } from "../data/StringTemplate";
import { parseDateInvariant } from "../util";
import { dayBefore, parseDateInvariant } from "../util";
import { GlobalCacheIdentifier } from "../util/GlobalCacheIdentifier";

export const Format = Fmt;
Expand Down Expand Up @@ -86,6 +86,12 @@ export function enableCultureSensitiveFormatting() {
return (value: any) => formatter.format(parseDateInvariant(value));
});

Fmt.registerFactory(["dayBefore", "daybefore"], (fmt: any, format = "yyyyMd hhmm") => {
let culture = Culture.getDateTimeCulture();
let formatter = culture.getFormatter(format);
return (value: any) => formatter.format(dayBefore(parseDateInvariant(value)));
});

setGetFormatCacheCallback(() => {
let cache = getCurrentCultureCache();
if (!cache.formatCache) cache.formatCache = {};
Expand Down
11 changes: 11 additions & 0 deletions packages/cx/src/util/Format.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,17 @@ describe("Format", function () {
});
});

describe("daybefore", function () {
it("formats the date shifted back by one day", function () {
assert.equal(Format.value(new Date(2015, 3, 1, 5, 6, 14), "daybefore"), "3/31/2015 05:06");
assert.equal(Format.value(new Date(2015, 3, 1, 5, 6, 14), "dayBefore"), "3/31/2015 05:06");
});

it("steps back across month and year boundaries", function () {
assert.equal(Format.value(new Date(2021, 0, 1), "daybefore"), "12/31/2020 00:00");
});
});

describe("ellipsis", function () {
it("can shorten long texts", function () {
assert.equal(Format.value("This is a very long text.", "ellipsis;7"), "This...");
Expand Down
7 changes: 7 additions & 0 deletions packages/cx/src/util/Format.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import { isUndefined } from "../util/isUndefined";
import { isArray } from "../util/isArray";
import { capitalize } from "./capitalize";
import { parseDateInvariant } from "./date/parseDateInvariant";
import { dayBefore } from "./date/dayBefore";

//Culture dependent formatters are defined in the ui package.

Expand Down Expand Up @@ -98,6 +99,11 @@ let formatFactory: Record<string, (...args: any[]) => (value: any) => string> =
return (value: any) => date(value) + " " + time(value);
},

dayBefore: function () {
let datetime = formatFactory.datetime();
return (value: any) => datetime(dayBefore(parseDateInvariant(value)));
},

ellipsis: function (part0, length, where) {
length = Number(length);
if (!(length > 3)) length = 10;
Expand Down Expand Up @@ -168,6 +174,7 @@ formatFactory.ps = formatFactory.percentageSign;
formatFactory.d = formatFactory.date;
formatFactory.t = formatFactory.time;
formatFactory.dt = formatFactory.datetime;
formatFactory.daybefore = formatFactory.dayBefore;
formatFactory.zeropad = formatFactory.zeroPad;
formatFactory.leftpad = formatFactory.leftPad;
formatFactory.capitalize = formatFactory.capitalize;
Expand Down
15 changes: 15 additions & 0 deletions packages/cx/src/util/date/dayBefore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* Returns a new `Date` representing the calendar day before the given date,
* keeping the same time of day. Month and year boundaries are handled
* automatically. The input is not mutated.
*
* Useful for displaying the exclusive end of a date range as an inclusive
* value, e.g. a period ending at `2021-01-01` shown as `Dec 2020`.
* @param date
* @returns {Date}
*/
export function dayBefore(date: Date): Date {
let result = new Date(date.getTime());
result.setDate(result.getDate() - 1);
return result;
}
1 change: 1 addition & 0 deletions packages/cx/src/util/date/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./dateDiff";
export * from "./dayBefore";
export * from "./zeroTime";
export * from "./monthStart";
export * from "./lowerBoundCheck";
Expand Down
Loading