Skip to content

Commit

Permalink
Merge pull request #40 from implydata/more_floorable
Browse files Browse the repository at this point in the history
Make more durations floorable and fix materialize
  • Loading branch information
jgoz authored Jan 17, 2025
2 parents fa3ef44 + cb6d9e3 commit 81f8796
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 7 deletions.
5 changes: 5 additions & 0 deletions .changeset/modern-games-sneeze.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'chronoshift': minor
---

Make more durations floorable and fix materialize
2 changes: 1 addition & 1 deletion .idea/inspectionProfiles/Project_Default.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 28 additions & 4 deletions src/duration/duration.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -198,18 +198,26 @@ describe('Duration', () => {
});
});

describe('#isFloorable', () => {
describe('#isFloorable / #makeFloorable', () => {
it('works on floorable things', () => {
const vs = 'P1Y P5Y P10Y P100Y P1M P2M P3M P4M P1D'.split(' ');
const vs = 'P1Y P5Y P10Y P100Y P1M P2M P3M P4M P1D P2D P3D P5D'.split(' ');
for (const v of vs) {
expect(Duration.fromJS(v).isFloorable(), v).toEqual(true);
expect(Duration.fromJS(v).makeFloorable().toString(), v).toEqual(v);
}
});

it('works on not floorable things', () => {
const vs = 'P1Y1M P5M P2D P3D'.split(' ');
const vs = [
{ unfloorable: 'P1Y1M', floorable: 'P1Y' },
{ unfloorable: 'P5M', floorable: 'P1M' },
{ unfloorable: 'P4D', floorable: 'P1D' },
];
for (const v of vs) {
expect(Duration.fromJS(v).isFloorable(), v).toEqual(false);
expect(Duration.fromJS(v.unfloorable).isFloorable(), v.unfloorable).toEqual(false);
expect(Duration.fromJS(v.floorable).makeFloorable().toString(), v.unfloorable).toEqual(
v.floorable,
);
}
});
});
Expand Down Expand Up @@ -458,6 +466,22 @@ describe('Duration', () => {
});

describe('#materialize', () => {
it('works for hours', () => {
const pt1h = new Duration('PT1H');

expect(
pt1h.materialize(
new Date('2012-10-29T00:05:00-07:00'),
new Date('2012-10-29T03:05:00-07:00'),
TZ_LA,
),
).toEqual([
new Date('2012-10-29T01:00:00-07:00'),
new Date('2012-10-29T02:00:00-07:00'),
new Date('2012-10-29T03:00:00-07:00'),
]);
});

it('works for weeks', () => {
const p1w = new Duration('P1W');

Expand Down
12 changes: 11 additions & 1 deletion src/duration/duration.ts
Original file line number Diff line number Diff line change
Expand Up @@ -274,6 +274,16 @@ export class Duration implements ImmutableClassInstance<DurationValue, string> {
return siblings % span === 0;
}

public makeFloorable(): Duration {
if (this.isFloorable()) return this;
const { singleSpan, spans } = this;
if (singleSpan) return new Duration({ [singleSpan]: 1 });
for (const span of SPANS_WITH_WEEK) {
if (spans[span]) return new Duration({ [span]: 1 });
}
return new Duration({ second: 1 });
}

/**
* Floors the date according to this duration.
* @param date The date to floor
Expand Down Expand Up @@ -358,7 +368,7 @@ export class Duration implements ImmutableClassInstance<DurationValue, string> {
*/
public materialize(start: Date, end: Date, timezone: Timezone, step = 1): Date[] {
const values: Date[] = [];
let iter = this.floor(start, timezone);
let iter = this.makeFloorable().ceil(start, timezone);
while (iter <= end) {
values.push(iter);
iter = this.shift(iter, timezone, step);
Expand Down
8 changes: 7 additions & 1 deletion src/floor-shift-ceil/floor-shift-ceil.ts
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ export type RoundFn = (dt: Date, roundTo: number, tz: Timezone) => Date;

export interface TimeShifterNoCeil {
canonicalLength: number;
siblings?: number;
siblings: number;
floor: AlignFn;
round: RoundFn;
shift: ShiftFn;
Expand Down Expand Up @@ -137,6 +137,7 @@ export const hour = timeShifterFiller({

export const day = timeShifterFiller({
canonicalLength: 24 * 3600000,
siblings: 30,
floor: (dt, tz) => {
if (tz.isUTC()) {
dt = new Date(dt.valueOf());
Expand Down Expand Up @@ -164,6 +165,7 @@ export const day = timeShifterFiller({

export const week = timeShifterFiller({
canonicalLength: 7 * 24 * 3600000,
siblings: 52,
floor: (dt, tz) => {
if (tz.isUTC()) {
dt = new Date(dt.valueOf());
Expand Down Expand Up @@ -272,9 +274,13 @@ export const year = timeShifterFiller({
shift: yearShift,
});

/**
* @deprecated use `new Duration('P${numDays}D')` instead
*/
export function getMultiDayShifter(numDays: number) {
return timeShifterFiller({
canonicalLength: 24 * 3600000 * numDays,
siblings: 1, // This is a no-op dummy
floor: day.floor,
shift: (dt, tz, step) => day.shift(dt, tz, step * numDays),
round: () => {
Expand Down

0 comments on commit 81f8796

Please sign in to comment.