dayjs
dayjs copied to clipboard
How to round to next/previous 15 minutes?
const now = dayjs(); // e.g. 'HH:mm' is 17:37
But what I want to modify the object to snap to 17:30
or 17:45
.
Is there a way to do it? "Rounding" only seems to be a thing in relative time, which is not what I'm looking for.
Friendly push.
@katerlouis did you find a solution?
I created my own ceil function, I think I originally stole it from moment-round
import inst, { PluginFunc, UnitType } from 'dayjs';
declare module 'dayjs' {
interface Dayjs {
ceil(unit: UnitType, amount: number): inst.Dayjs;
}
}
const ceil: PluginFunc = (option, dayjsClass) => {
dayjsClass.prototype.ceil = function (unit, amount) {
return this.add(amount - (this.get(unit) % amount), unit).startOf(unit);
};
};
export default ceil;
Can be used like
import dayjs from 'dayjs';
import ceil from './ceil';
dayjs.extend(ceil);
console.log(dayjs().ceil('minutes', 15).format());
I've created a version to round (up or down) to the nearest time.
19:52 becomes 19:50 19:53 becomes 19:55
const round: PluginFunc = (option, dayjsClass) => {
dayjsClass.prototype.round = function (amount, unit) {
const mod = this.get(unit as UnitType) % amount;
if(mod < amount / 2) {
return this.subtract(mod, unit).startOf(unit);
}
return this.add(amount - mod, unit).startOf(unit);
};
};
- I start to test @cjsewell solution and soon I found a bug, imho:
dayjs('2023-06-29T14:14:14+00:00').ceil(24 * 60, 'minutes').utc().format()
result is 2023-06-30T14:00:00+00:00', but I expected '2023-06-30T00:00:00+00:00'
- So this is the solution based on stackoverflow
import duration from "dayjs/plugin/duration";
export default (option, dayjsClass, dayjsFactory) => {
dayjsFactory.extend(duration);
// @see https://stackoverflow.com/a/39637877
const _round = function (amount, unit, method) {
const duration = dayjsFactory.duration(amount, unit);
return dayjsFactory(Math[method](this.valueOf() / duration.as("milliseconds")) * duration.as("milliseconds"));
};
"floor ceil round".split(" ").forEach((method) => {
dayjsClass.prototype[method] = function (amount, unit) {
return _round.call(this, amount, unit, method);
};
});
};