iamkun / dayjs

⏰ Day.js 2kB immutable date-time library alternative to Moment.js with the same modern API
https://day.js.org
MIT License
46.73k stars 2.28k forks source link

How to generate to date ranges? #1162

Open engineer-myoa opened 3 years ago

engineer-myoa commented 3 years ago

Currently, does dayjs support generating date ranges? Like this one. moment-range extension.

e.g.)

dayjs.ranges(
    dayjs("2020-10-10"),
    dayjs("2020-10-20"),
    "days"
)
// the result is [start, end]
// like [10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20]
// or [start, end)
// like [10, 11, 12, 13, 14, 15, 16, 17, 18, 19]

Please check if dayjs team can considered it.

iamkun commented 3 years ago

Looks cool, we could add it as a plugin.

smblee commented 3 years ago

Definitely cool idea. This is currently what I do in my application.

  let currentDate = dayjs(openTime);

  while (currentDate.isBefore(closeTime) || currentDate.isSame(closeTime)) {
    currentDate = currentDate.add(amount, unit);
    ranges.push(currentDate.format());
  }
engineer-myoa commented 3 years ago

Definitely cool idea. This is currently what I do in my application.

  let currentDate = dayjs(openTime);

  while (currentDate.isBefore(closeTime) || currentDate.isSame(closeTime)) {
    currentDate = currentDate.add(amount, unit);
    ranges.push(currentDate.format());
  }

It looks short, simple and powerful. But if it become to some plugin, It need to have fool proof. Is it the amount value mean interval? Maybe the amount parameter can be adjust it. or swap between value if it had reverse order.

startOfRange = dayjs.max(openTime, closeTime);
endOfRange dayjs.min(openTime, closeTime);

let currentDate = dayjs(startOfRange);

while (currentDate.isBefore(endOfRange) || currentDate.isSame(endOfRange)) {
    currentDate = currentDate.add(amount, unit);
    ranges.push(currentDate.format());
  }
smblee commented 3 years ago

Yea theres a lot you can do with this (moment-range has a LOT more features).

amount and unit are the standard amount/unit (e.g. 30, 'minutes') used in the application. I think this code alone will get us started.

Envision contract to be something like: dayjs.range(start, finish, amount, unit, { ...other options })

dayjs.range(dayjs(), dayjs().add(1, 'day'), 15, 'minutes') => [...]

my example code above will be converted to

dayjs.range(start, end, 15, 'minutes').map(d => d.format()) => [...]

Some more features that could be added are...

^ definitely tricky and not sure how much it would be useful. I had some use cases where I had to do that, but I just rounded the start time to a "whole" number.

gy18505 commented 3 years ago

Looks cool, we could add it as a plugin.

well, has the plugin released yet?

kostia7alania commented 3 years ago

го

uffou commented 2 years ago

Sweet! can't wait for this :)

mikiastilahun commented 2 years ago

Any updates?

VictorPulzz commented 2 years ago

Please implement this!)

anttibull commented 2 years ago

100951

youhymuk commented 2 years ago

@iamkun Does any reason exist why this PR - https://github.com/iamkun/dayjs/pull/1580 hasn't merged yet? Many people are still waiting for this feature

echosonusharma commented 2 years ago

this might not be something you're looking for but i just need to create slots for a day based on minutes. i'm posting in case it ends up helping someone.

function formatMinutes(minutes) {
    let h = Math.floor(minutes / 60);
    let m = minutes % 60;
    h = h < 10 ? '0' + h : h;
    m = m < 10 ? '0' + m : m;
    return h + ':' + m;
}

function slots(time, bufferTime) {
    const slotArray = [];

    const slotsToCreate = Math.floor(1440 / (time + bufferTime));

    for (let i = 0; i <= slotsToCreate; i++) {
        const minutes = (time + bufferTime) * i;

        const slotObj = {};
        slotObj[minutes] = formatMinutes(minutes);
        slotArray.push(slotObj);
    }
    return slotArray;
}

console.log(slots(60, 15));

this worked for my needs, use the day you want and for generating slots using this. will return something like this

[
  { '0': '00:00' },    { '75': '01:15' },
  { '150': '02:30' },  { '225': '03:45' },
  { '300': '05:00' },  { '375': '06:15' },
  { '450': '07:30' },  { '525': '08:45' },
  { '600': '10:00' },  { '675': '11:15' },
  { '750': '12:30' },  { '825': '13:45' },
  { '900': '15:00' },  { '975': '16:15' },
  { '1050': '17:30' }, { '1125': '18:45' },
  { '1200': '20:00' }, { '1275': '21:15' },
  { '1350': '22:30' }, { '1425': '23:45' }
]
newbie78 commented 1 year ago

Hi all!

https://github.com/fsubal/dayjs-range-support this plugin is the best choice for range like in moment

it would be great to add it to the main package

17 commented 1 year ago
// range(1682870400000,1685548799999, [1, 'day'] or 'day', 'DD')
export function dayjsRange (from, to, step, format) {
  const list = []
  let current = dayjs(from)
  while (current.isBefore(to)) {
    list.push(format ? current.format(format) : current)
    current = current.add(...(isString(step) ? [1, step] : step))
  }
  return list
}

This is currently what I do in my application.

KevinHu-1024 commented 1 year ago

👋 Hi all and @iamkun , any update for the day ranges feature?

karlhorky commented 1 year ago

@17 thanks for that! A modified version:

import type { Dayjs, ManipulateType } from 'dayjs';

/**
 * Create a range of Day.js dates between a start and end date.
 *
 * ```js
 * dayjsRange(dayjs('2021-04-03'), dayjs('2021-04-05'), 'day');
 * // => [dayjs('2021-04-03'), dayjs('2021-04-04'), dayjs('2021-04-05')]
 * ```
 */
export function dayjsRange(start: Dayjs, end: Dayjs, unit: ManipulateType) {
  const range = [];
  let current = start;
  while (!current.isAfter(end)) {
    range.push(current);
    current = current.add(1, unit);
  }
  return range;
}

Or if you only need days between a start and end:

import type { Dayjs } from 'dayjs';

/**
 * Create a range of Day.js dates between a start and end date.
 *
 * ```js
 * getDaysBetween(dayjs('2021-04-03'), dayjs('2021-04-05'));
 * // => [dayjs('2021-04-03'), dayjs('2021-04-04'), dayjs('2021-04-05')]
 * ```
 */
export function getDaysBetween(start: Dayjs, end: Dayjs) {
  const range = [];
  let current = start;
  while (!current.isAfter(end)) {
    range.push(current);
    current = current.add(1, 'days');
  }
  return range;
}
danieldram commented 11 months ago

I added the ability to set the direction to get previous dates and future dates list also written in typescript. Thank you for OP for the original code.

import dayjs from "dayjs";
import { isString } from "lodash";

interface IDayjsRange {
  from: string;
  to: string;
  stepNumber: number;
  stepIncrement: "day" | "month" | "year" | "week";
  format: string;
  direction: "subtract" | "add";
}
export function dayjsRange({
  from = "",
  to = "",
  stepNumber = 1,
  stepIncrement = "day",
  format = "DD-MM-YYYY",
  direction = "add",
}: IDayjsRange) {
  const list = [];
  let current = dayjs(from);
  const ending = dayjs(to);

  const setCondition = () =>
    direction === "add" ? current.isBefore(ending) : current.isAfter(ending);
  let condition = setCondition();

  while (condition) {
    list.push(format ? current.format(format) : current);
    current = current[direction](stepNumber, stepIncrement);
    condition = setCondition();
  }
  return list;
}

Usage:

 const previousDates = dayjsRange({
    from: startDate.toISOString(),
    to: startDate.subtract(5, "years").toISOString(),
    stepNumber: 1,
    stepIncrement: "year",
    direction: "subtract",
    format: "YYYY",
  });

  const futureDates = dayjsRange({
    from: startDate.toISOString(),
    to: startDate.add(5, "years").toISOString(),
    stepNumber: 1,
    stepIncrement: "year",
    direction: "add",
    format: "YYYY",
  });
mr-moon commented 3 weeks ago

Generating ranges in built-in units - is simple. Here's an example on how to generate day ranges.

function* range(a, b, unit) {
  let d = a.clone().startOf(unit).subtract(1, unit);
  b = b.subtract(1, unit);
  while (d < b) {
    yield (d = d.add(1, unit));
  }
  return false;
}

Array.from(range(dayjs(), dayjs().add(1, 'M'), 'd')); // [a+1d, a+2d, a+3d ...]

You can modify date increments as you need. No real need for a plugin.

Yvad60 commented 2 weeks ago

Any updates?