date-fns#endOfWeek TypeScript Examples

The following examples show how to use date-fns#endOfWeek. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: dateUtils.tsx    From symphony-ui-toolkit with Apache License 2.0 6 votes vote down vote up
/**
 * Return a list of translated weekdays, the starting day depends on locale
 * @param date
 * @param locale
 * @param pattern
 */
function getWeekdays(date: Date, locale: Locale, pattern: string): string[] {
  const arr = eachDayOfInterval({
    start: startOfWeek(date, { locale }),
    end: endOfWeek(date, { locale }),
  });

  return arr.map((item) => {
    return format(item, pattern, { locale });
  });
}
Example #2
Source File: dateUtils.tsx    From symphony-ui-toolkit with Apache License 2.0 6 votes vote down vote up
export function getDaysNeededForNextMonth(date: Date, locale: Locale) {
  const daysNeededForLastMonth = getDaysNeededForLastMonth(date, locale);
  const lastDayOfWeek = endOfWeek(date, { locale });

  const endDate = lastDayOfMonth(date);

  // getDay return the value of the weekday from 0 to 6
  // i.e enDate is the Friday -> getDay(enDate) = 5
  // i.e. lastDayOfWeek is a Saturday -> getDay(lastDayOfWeek) = 6 (depends on locale)
  // + 7 and the modulo to ensure the result is positive value is between 0 and 6 (javascript % can return negative value)
  let daysNeededForNextMonth =
    (getDay(lastDayOfWeek) - getDay(endDate) + 7) % 7;
  if (daysNeededForLastMonth + getDaysInMonth(date) <= 35) {
    daysNeededForNextMonth += 7;
  }
  return daysNeededForNextMonth;
}
Example #3
Source File: datecalc.ts    From calendar-hack with MIT License 6 votes vote down vote up
export function calcPlanDates(planWeeks: number, planEndsOn: Date): PlanDates {
    const end = startOfDay(endOfWeek(planEndsOn, { weekStartsOn: 1 }));
    const planStart = subDays(planEndsOn, planWeeks * 7 - 1);
    const start = startOfWeek(planStart, { weekStartsOn: 1 });
    const totalDays = 1 + differenceInCalendarDays(end, start);
    if (0 !== totalDays % 7) {
        throw new Error("total days %7 !==0: " + totalDays);
    }
    const weekCount = totalDays / 7;
    let result = {
        start: start,
        planStartDate: planStart,
        planEndDate: planEndsOn, // before or on race day
        end: end, // race day or beyond
        weekCount: weekCount
    }
    return result;
}
Example #4
Source File: dategrid.ts    From calendar-hack with MIT License 6 votes vote down vote up
setEvent(date: Date, event: T | undefined) {
        const k = key(date);
        if (event) {
            this._events.set(k, event);
            // min/max/first/last/weekCount maintenance
            if (!this._max || isAfter(date, this._max))
                this._max = date;
            this._last = startOfDay(endOfWeek(this._max, { weekStartsOn: 1 }))
            if (!this._min || isBefore(date, this._min))
                this._min = date;
            this._first = startOfWeek(this._min, { weekStartsOn: 1 })
            this._weekCount = differenceInWeeks(startOfDay(addDays(this._last, 1)), this._first);
        } else {
            this._events.delete(k);
        }
    }
Example #5
Source File: DayPicker.tsx    From symphony-ui-toolkit with Apache License 2.0 5 votes vote down vote up
handleKeyDownCell(e: React.KeyboardEvent, date: Date, modifers): void {
    const { locale, dir } = this.props;
    const { currentMonth } = this.state;
    if (e.key !== Keys.ESC) {
      cancelEvent(e);
    }

    const direction = dir === 'ltr' ? 1 : -1;
    const MAX_STEP_TO_CHECK = 7;
    let nextCell;
    switch (e.key) {
    case Keys.TAB:
      if (this.dayPicker) {
        if (e.shiftKey) {
          this.dayPicker
            .querySelector('.tk-daypicker-header--nextYear')
            .focus();
        } else {
          this.dayPicker.querySelector('.tk-daypicker-today').focus();
        }
      }
      break;
    case Keys.SPACE:
    case Keys.SPACEBAR:
    case Keys.ENTER:
      // eslint-disable-next-line no-case-declarations
      const { onDayClick } = this.props;
      onDayClick(date, modifers);
      break;
    case Keys.PAGE_UP:
      if (e.shiftKey) {
        this.monthNavigation(date, addYears(currentMonth, -1));
      } else {
        this.monthNavigation(date, addMonths(currentMonth, -1));
      }
      break;
    case Keys.PAGE_DOWN:
      if (e.shiftKey) {
        this.monthNavigation(date, addYears(currentMonth, 1));
      } else {
        this.monthNavigation(date, addMonths(currentMonth, 1));
      }
      break;
    case Keys.HOME:
      // eslint-disable-next-line no-case-declarations
      const firstDayOfWeek = startOfWeek(date, { locale });
      nextCell =
          firstDayOfWeek.getDate() <= date.getDate()
            ? firstDayOfWeek
            : startOfMonth(date);
      this.focusOnlyEnabledCell(nextCell, 'next', MAX_STEP_TO_CHECK);
      break;
    case Keys.END:
      // eslint-disable-next-line no-case-declarations
      const lastDayOfWeek = endOfWeek(date, { locale });
      nextCell =
          date.getDate() <= lastDayOfWeek.getDate()
            ? lastDayOfWeek
            : lastDayOfMonth(date);
      this.focusOnlyEnabledCell(nextCell, 'previous', MAX_STEP_TO_CHECK);
      break;
    case Keys.ARROW_LEFT:
      this.arrowNavigation(date, addDays(date, -1 * direction));
      break;
    case Keys.ARROW_UP:
      this.arrowNavigation(date, addDays(date, -7));
      break;
    case Keys.ARROW_RIGHT:
      this.arrowNavigation(date, addDays(date, 1 * direction));
      break;
    case Keys.ARROW_DOWN:
      this.arrowNavigation(date, addDays(date, 7));
      break;
    default:
      break;
    }
  }
Example #6
Source File: dateUtils.ts    From ant-extensions with MIT License 5 votes vote down vote up
parseDate = (dt?: string, rounded?: "start" | "end"): ParsedDate => {
  if (dt && isDate(dt)) {
    return parseISO(dt);
  } else if (dt && isDateLike(dt)) {
    const parts = getDateParts(dt);

    if (parts) {
      const { part, op, diff } = parts;
      const diffNum = parseInt(`${op}${diff}`, 10);
      let date = startOfMinute(new Date());

      switch (part) {
        case DateParts.NOW:
          return date;
        case DateParts.DECADE:
          if (rounded) {
            date = (rounded === "start" ? startOfDecade : endOfDecade)(date);
          }
          return addYears(date, diffNum * 10);
        case DateParts.YEAR:
          if (rounded) {
            date = (rounded === "start" ? startOfYear : endOfYear)(date);
          }
          return addYears(date, diffNum);
        case DateParts.QUARTER:
          if (rounded) {
            date = (rounded === "start" ? startOfQuarter : endOfQuarter)(date);
          }
          return addQuarters(date, diffNum);
        case DateParts.MONTH:
          if (rounded) {
            date = (rounded === "start" ? startOfMonth : endOfMonth)(date);
          }
          return addMonths(date, diffNum);
        case DateParts.WEEK:
          if (rounded) {
            date = (rounded === "start" ? startOfWeek : endOfWeek)(date);
          }
          return addWeeks(date, diffNum);
        case DateParts.DAY:
          if (rounded) {
            date = (rounded === "start" ? startOfDay : endOfDay)(date);
          }
          return addDays(date, diffNum);
        case DateParts.HOUR:
          if (rounded) {
            date = (rounded === "start" ? startOfHour : endOfHour)(date);
          }
          return addHours(date, diffNum);
        case DateParts.MINUTE:
          if (rounded) {
            date = (rounded === "start" ? startOfMinute : endOfMinute)(date);
          }
          return addMinutes(date, diffNum);
      }
    }
  }
  return undefined;
}
Example #7
Source File: timetable.page.ts    From radiopanel with GNU General Public License v3.0 5 votes vote down vote up
public startDragToCreate(
		segment: any,
		mouseDownEvent: MouseEvent,
		segmentElement: HTMLElement
	) {
		const { tenant } = this.sessionQuery.getValue();

		const temporarySlot: CalendarEvent = {
			id: this.slots.length,
			title: 'New slot',
			start: segment.date,
			end: moment(segment.date).add((tenant?.settings?.minimumSlotDuration || 30) > 60 ? (tenant?.settings?.minimumSlotDuration || 30) : 60, 'minutes').toDate(),
			color: {
				primary: '#000',
				secondary: '#000'
			},
			meta: {
				tmpEvent: true,
				...this.user
			}
		};

		this.slots = [...this.slots, temporarySlot];
		const scrollOffset = document.querySelector('.o-content').scrollTop;
		const segmentPosition = segmentElement.getBoundingClientRect();
		this.dragToCreateActive = true;
		const endOfView = endOfWeek(this.viewDate, {
			weekStartsOn: 1
		});

		fromEvent(document, 'mousemove')
			.pipe(
				finalize(() => {
					delete temporarySlot.meta.tmpEvent;
					this.dragToCreateActive = false;
					this.handleSlotCreate(temporarySlot);
					this.refresh();
				}),
				takeUntil(fromEvent(document, 'mouseup')),
				// debounceTime(10)
			)
			.subscribe((mouseMoveEvent: MouseEvent) => {
				const boundingRect = this.timetableRoot.nativeElement.getBoundingClientRect();
				const minutesDiff = ceilToNearest(
					mouseMoveEvent.clientY - segmentPosition.top - (boundingRect.top - this.timetableRoot.nativeElement.offsetTop) - scrollOffset,
					30
				);

				const daysDiff =
					floorToNearest(
						mouseMoveEvent.clientX - segmentPosition.left,
						segmentPosition.width
					) / segmentPosition.width;

				const newEnd = addDays(
					addMinutes(segment.date, minutesDiff),
					daysDiff
				);

				const totalDiff = (minutesDiff + (daysDiff * 24 * 60));

				if (newEnd > segment.date && newEnd < moment(endOfView).add(1, 'minute').toDate() && totalDiff <= (tenant?.settings?.maximumSlotDuration || 1440) && totalDiff >= (tenant?.settings?.minimumSlotDuration || 30)) {
					temporarySlot.end = newEnd;
				}

				this.refresh();
			});
	}
Example #8
Source File: date.ts    From ngx-gantt with MIT License 5 votes vote down vote up
endOfWeek(options?: { locale?: Locale; weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 }): GanttDate {
        return new GanttDate(endOfWeek(this.value, options));
    }
Example #9
Source File: CalendarHeatmap.tsx    From apps with GNU Affero General Public License v3.0 4 votes vote down vote up
export default function CalendarHeatmap<T extends { date: string }>({
  startDate,
  endDate,
  gutterSize = 2,
  values,
  valueToCount,
  valueToTooltip,
}: CalendarHeatmapProps<T>): ReactElement {
  const squareSizeWithGutter = SQUARE_SIZE + gutterSize;

  const numEmptyDaysAtEnd = DAYS_IN_WEEK - 1 - endDate.getDay();
  const numEmptyDaysAtStart = startDate.getDay();
  const startDateWithEmptyDays = addDays(startDate, -numEmptyDaysAtStart);

  const dateDifferenceInDays = differenceInDays(endDate, startDate);

  const numDaysRoundedToWeek =
    dateDifferenceInDays + numEmptyDaysAtStart + numEmptyDaysAtEnd;
  const weekCount = Math.ceil(numDaysRoundedToWeek / DAYS_IN_WEEK);

  const weekWidth = DAYS_IN_WEEK * squareSizeWithGutter;

  const width =
    weekCount * squareSizeWithGutter - (gutterSize - weekdayLabelSize);
  const height = weekWidth + (MONTH_LABEL_SIZE - gutterSize);

  const bins = useMemo<number[]>(
    () => getBins(values.map(valueToCount)),
    [values, valueToCount],
  );
  const computedValues = useMemo<
    Record<number, { count: number; date: Date; bin: number; originalValue: T }>
  >(
    () =>
      values.reduce((acc, value) => {
        const date = new Date(value.date);
        const index = differenceInDays(date, startDateWithEmptyDays);
        if (index < 0) {
          return acc;
        }
        const count = valueToCount(value);
        acc[index] = {
          count,
          bin: getBin(count, bins),
          date,
          originalValue: value,
        };
        return acc;
      }, {}),
    [values, valueToCount, startDate, endDate, bins],
  );

  const getMonthLabelCoordinates = (weekIndex: number): [number, number] => [
    weekIndex * squareSizeWithGutter,
    (MONTH_LABEL_SIZE - MONTH_LABEL_GUTTER_SIZE) / 2 + 1,
  ];

  const renderMonthLabels = (): ReactNode => {
    const weekRange = getRange(weekCount - 2);
    return weekRange.map((weekIndex) => {
      const date = endOfWeek(
        addDays(startDateWithEmptyDays, weekIndex * DAYS_IN_WEEK),
      );
      const [x, y] = getMonthLabelCoordinates(weekIndex);
      return date.getDate() >= DAYS_IN_WEEK &&
        date.getDate() <= 2 * DAYS_IN_WEEK - 1 ? (
        <text key={weekIndex} x={x} y={y} style={labelStyle}>
          {MONTH_LABELS[date.getMonth()]}
        </text>
      ) : null;
    });
  };

  const getWeekdayLabelCoordinates = (dayIndex: number): [number, number] => [
    0,
    (dayIndex + 1) * SQUARE_SIZE + dayIndex * gutterSize,
  ];

  const renderWeekdayLabels = (): ReactNode => {
    return DAY_LABELS.map((weekdayLabel, dayIndex) => {
      const [x, y] = getWeekdayLabelCoordinates(dayIndex);
      return weekdayLabel.length ? (
        <text key={`${x}${y}`} x={x} y={y} style={labelStyle}>
          {weekdayLabel}
        </text>
      ) : null;
    });
  };

  const getSquareCoordinates = (dayIndex: number): [number, number] => [
    0,
    dayIndex * squareSizeWithGutter,
  ];

  const renderSquare = (dayIndex: number, index: number): ReactNode => {
    const indexOutOfRange =
      index < numEmptyDaysAtStart ||
      index >= numEmptyDaysAtStart + dateDifferenceInDays;
    if (indexOutOfRange) {
      return null;
    }
    const [x, y] = getSquareCoordinates(dayIndex);
    const value = computedValues[index];
    const bin = value?.bin || 0;
    const attrs = binsAttributes[bin];
    return (
      <SimpleTooltip
        content={valueToTooltip(
          value?.originalValue,
          addDays(startDateWithEmptyDays, index),
        )}
        duration={0}
        delay={[0, 70]}
        container={{
          paddingClassName: 'py-3 px-4',
          roundedClassName: 'rounded-3',
        }}
      >
        <g>
          <rect
            key={index}
            width={SQUARE_SIZE}
            height={SQUARE_SIZE}
            x={x}
            y={y}
            rx="3"
            {...attrs}
          />
          {!bin && (
            <rect
              width={SQUARE_SIZE - 2}
              height={SQUARE_SIZE - 2}
              x={x + 1}
              y={y + 1}
              rx="2"
              fill="var(--theme-background-primary)"
            />
          )}
        </g>
      </SimpleTooltip>
    );
  };

  const renderWeek = (weekIndex: number): ReactNode => {
    return (
      <g
        key={weekIndex}
        transform={`translate(${weekIndex * squareSizeWithGutter}, 0)`}
      >
        {getRange(DAYS_IN_WEEK).map((dayIndex) =>
          renderSquare(dayIndex, weekIndex * DAYS_IN_WEEK + dayIndex),
        )}
      </g>
    );
  };

  const renderAllWeeks = (): ReactNode =>
    getRange(weekCount).map((weekIndex) => renderWeek(weekIndex));

  return (
    <svg
      width={width}
      viewBox={`0 0 ${width} ${height}`}
      onMouseDown={(e) => e.preventDefault()}
    >
      <g transform={`translate(${weekdayLabelSize}, 0)`}>
        {renderMonthLabels()}
      </g>
      <g transform={`translate(0, ${MONTH_LABEL_SIZE})`}>
        {renderWeekdayLabels()}
      </g>
      <g transform={`translate(${weekdayLabelSize}, ${MONTH_LABEL_SIZE})`}>
        {renderAllWeeks()}
      </g>
    </svg>
  );
}
Example #10
Source File: App.tsx    From calendar-hack with MIT License 4 votes vote down vote up
App: React.FC = () => {
  const [{ u, p, d }, setq] = useQueryParams({ u: StringParam, p: StringParam, d: DateParam });
  const [selectedUnits, setSelectedUnits] = useState<Units>((u === 'mi' || u === 'km') ? u : 'mi')
  var [selectedPlan, setSelectedPlan] = useState((p && availablePlansById[p]) ? availablePlansById[p] : availablePlans[0]);
  var [planEndDate, setPlanEndDate] = useState((d && isAfter(d, new Date())) ? d : addWeeks(endOfWeek(new Date(), { weekStartsOn: 1 }), 20));
  var [racePlan, setRacePlan] = useState<RacePlan | undefined>(undefined);
  var [undoHistory, setUndoHistory] = useState([] as RacePlan[]);

  useEffect(() => {
    initialLoad(selectedPlan, planEndDate, selectedUnits);
  }, []);

  const [, forceUpdate] = React.useReducer((x) => x + 1, 0);
  React.useEffect(() => {
    // listen for changes to the URL and force the app to re-render
    history.listen(() => {
      forceUpdate();
    });
  }, []);

  const getParams = (units: Units, plan: AvailablePlan, date: Date) => {
    return {
      u: units,
      p: plan.id,
      d: date,
    }
  }

  const initialLoad = async (plan: AvailablePlan, endDate: Date, units: Units) => {
    const racePlan = build(await planRepo.fetch(plan), endDate)
    setRacePlan(racePlan);
    setUndoHistory([...undoHistory, racePlan]);
    setq(getParams(units, plan, endDate));
  }

  const onSelectedPlanChange = async (plan: AvailablePlan) => {
    const racePlan = build(await planRepo.fetch(plan), planEndDate);
    setSelectedPlan(plan);
    setRacePlan(racePlan);
    setUndoHistory([racePlan]);
    setq(getParams(selectedUnits, plan, planEndDate));
  }

  const onSelectedEndDateChange = async (date: Date) => {
    const racePlan = build(await planRepo.fetch(selectedPlan), date);
    setPlanEndDate(date);
    setRacePlan(racePlan);
    setUndoHistory([racePlan]);
    setq(getParams(selectedUnits, selectedPlan, date));
  }

  const onSelectedUnitsChanged = (u: Units) => {
    setSelectedUnits(u);
    setq(getParams(u, selectedPlan, planEndDate));
  }

  function swapDates(d1: Date, d2: Date): void {
    if (racePlan) {
      const newRacePlan = swap(racePlan, d1, d2);
      setRacePlan(newRacePlan);
      setUndoHistory([...undoHistory, newRacePlan]);
    }
  }

  function doSwapDow(dow1: dayOfWeek, dow2: dayOfWeek) {
    if (racePlan) {
      const newRacePlan = swapDow(racePlan, dow1, dow2);
      setRacePlan(newRacePlan);
      setUndoHistory([...undoHistory, newRacePlan]);
    }
  }

  function swapWeeks(w1: number, w2: number): void {
    if (racePlan) {
      racePlan.dateGrid.swapWeeks(w1, w2);
      setRacePlan(racePlan);
      setUndoHistory([...undoHistory, racePlan]);
    }
  }

  function downloadHandler() {
    if (racePlan) {
      const iCalEventsStr = toIcal(racePlan, selectedUnits)
      if (iCalEventsStr) {
        download(iCalEventsStr, "plan", "ics");
      }
    }
  }

  function undoHandler() {
    if (undoHistory?.length >= 0) {
      undoHistory.pop();
    }
    setRacePlan(undoHistory[undoHistory.length - 1]);
  }

  return (
    <ThemeProvider theme={theme}>
      <Toolbar downloadHandler={downloadHandler} />
      <PlanAndDate units={selectedUnits} availablePlans={availablePlans} selectedPlan={selectedPlan} selectedDate={planEndDate}
        dateChangeHandler={onSelectedEndDateChange} selectedPlanChangeHandler={onSelectedPlanChange} unitsChangeHandler={onSelectedUnitsChanged}
        downloadHandler={downloadHandler}
      />
      <SecondToolbar>
        <UnitsDiv>
          <UnitsButtons units={selectedUnits} unitsChangeHandler={onSelectedUnitsChanged} />
        </UnitsDiv>
        <DownloadButton downloadHandler={downloadHandler} />
        <UndoButton disabled={undoHistory.length <= 1} undoHandler={undoHandler} />
      </SecondToolbar>
      <PlanDetailsCard racePlan={racePlan} />
      <MainUI>
        {racePlan && <CalendarGrid racePlan={racePlan} units={selectedUnits} swap={swapDates} swapDow={doSwapDow} swapWeeks={swapWeeks} />}
      </MainUI>
    </ThemeProvider>
  )
}