sanity-plugin-recurring-dates 1.3.0 → 1.3.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -11,6 +11,7 @@ var lodash = require('lodash');
11
11
  var React = require('react');
12
12
  var rrule = require('rrule');
13
13
  var sanityPluginUtils = require('sanity-plugin-utils');
14
+ var dateFnsTz = require('date-fns-tz');
14
15
  var legacyDateFormat = require('@sanity/util/legacyDateFormat');
15
16
  function _interopNamespaceCompat(e) {
16
17
  if (e && typeof e === 'object' && 'default' in e) return e;
@@ -2731,20 +2732,84 @@ process.env.NODE_ENV !== "production" ? {
2731
2732
  children: PropTypes.node.isRequired,
2732
2733
  className: PropTypes.string
2733
2734
  } : {};
2734
- function toInteger(dirtyNumber) {
2735
- if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) {
2736
- return NaN;
2737
- }
2738
- var number = Number(dirtyNumber);
2739
- if (isNaN(number)) {
2740
- return number;
2741
- }
2742
- return number < 0 ? Math.ceil(number) : Math.floor(number);
2743
- }
2744
- function requiredArgs(required, args) {
2745
- if (args.length < required) {
2746
- throw new TypeError(required + ' argument' + (required > 1 ? 's' : '') + ' required, but only ' + args.length + ' present');
2747
- }
2735
+
2736
+ /**
2737
+ * @module constants
2738
+ * @summary Useful constants
2739
+ * @description
2740
+ * Collection of useful date constants.
2741
+ *
2742
+ * The constants could be imported from `date-fns/constants`:
2743
+ *
2744
+ * ```ts
2745
+ * import { maxTime, minTime } from "./constants/date-fns/constants";
2746
+ *
2747
+ * function isAllowedTime(time) {
2748
+ * return time <= maxTime && time >= minTime;
2749
+ * }
2750
+ * ```
2751
+ */
2752
+
2753
+ /**
2754
+ * @constant
2755
+ * @name millisecondsInWeek
2756
+ * @summary Milliseconds in 1 week.
2757
+ */
2758
+ const millisecondsInWeek = 604800000;
2759
+
2760
+ /**
2761
+ * @constant
2762
+ * @name constructFromSymbol
2763
+ * @summary Symbol enabling Date extensions to inherit properties from the reference date.
2764
+ *
2765
+ * The symbol is used to enable the `constructFrom` function to construct a date
2766
+ * using a reference date and a value. It allows to transfer extra properties
2767
+ * from the reference date to the new date. It's useful for extensions like
2768
+ * [`TZDate`](https://github.com/date-fns/tz) that accept a time zone as
2769
+ * a constructor argument.
2770
+ */
2771
+ const constructFromSymbol = Symbol.for("constructDateFrom");
2772
+
2773
+ /**
2774
+ * @name constructFrom
2775
+ * @category Generic Helpers
2776
+ * @summary Constructs a date using the reference date and the value
2777
+ *
2778
+ * @description
2779
+ * The function constructs a new date using the constructor from the reference
2780
+ * date and the given value. It helps to build generic functions that accept
2781
+ * date extensions.
2782
+ *
2783
+ * It defaults to `Date` if the passed reference date is a number or a string.
2784
+ *
2785
+ * Starting from v3.7.0, it allows to construct a date using `[Symbol.for("constructDateFrom")]`
2786
+ * enabling to transfer extra properties from the reference date to the new date.
2787
+ * It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
2788
+ * that accept a time zone as a constructor argument.
2789
+ *
2790
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
2791
+ *
2792
+ * @param date - The reference date to take constructor from
2793
+ * @param value - The value to create the date
2794
+ *
2795
+ * @returns Date initialized using the given date and value
2796
+ *
2797
+ * @example
2798
+ * import { constructFrom } from "./constructFrom/date-fns";
2799
+ *
2800
+ * // A function that clones a date preserving the original type
2801
+ * function cloneDate<DateType extends Date>(date: DateType): DateType {
2802
+ * return constructFrom(
2803
+ * date, // Use constructor from the given date
2804
+ * date.getTime() // Use the date value to create a new date
2805
+ * );
2806
+ * }
2807
+ */
2808
+ function constructFrom(date, value) {
2809
+ if (typeof date === "function") return date(value);
2810
+ if (date && typeof date === "object" && constructFromSymbol in date) return date[constructFromSymbol](value);
2811
+ if (date instanceof Date) return new date.constructor(value);
2812
+ return new Date(value);
2748
2813
  }
2749
2814
 
2750
2815
  /**
@@ -2761,11 +2826,19 @@ function requiredArgs(required, args) {
2761
2826
  *
2762
2827
  * If the argument is none of the above, the function returns Invalid Date.
2763
2828
  *
2829
+ * Starting from v3.7.0, it clones a date using `[Symbol.for("constructDateFrom")]`
2830
+ * enabling to transfer extra properties from the reference date to the new date.
2831
+ * It's useful for extensions like [`TZDate`](https://github.com/date-fns/tz)
2832
+ * that accept a time zone as a constructor argument.
2833
+ *
2764
2834
  * **Note**: *all* Date arguments passed to any *date-fns* function is processed by `toDate`.
2765
2835
  *
2766
- * @param {Date|Number} argument - the value to convert
2767
- * @returns {Date} the parsed date in the local time zone
2768
- * @throws {TypeError} 1 argument required
2836
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
2837
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
2838
+ *
2839
+ * @param argument - The value to convert
2840
+ *
2841
+ * @returns The parsed date in the local time zone
2769
2842
  *
2770
2843
  * @example
2771
2844
  * // Clone the date:
@@ -2777,27 +2850,15 @@ function requiredArgs(required, args) {
2777
2850
  * const result = toDate(1392098430000)
2778
2851
  * //=> Tue Feb 11 2014 11:30:30
2779
2852
  */
2780
- function toDate(argument) {
2781
- requiredArgs(1, arguments);
2782
- var argStr = Object.prototype.toString.call(argument);
2783
-
2784
- // Clone the date
2785
- if (argument instanceof Date || _typeof(argument) === 'object' && argStr === '[object Date]') {
2786
- // Prevent the date to lose the milliseconds when passed to new Date() in IE10
2787
- return new Date(argument.getTime());
2788
- } else if (typeof argument === 'number' || argStr === '[object Number]') {
2789
- return new Date(argument);
2790
- } else {
2791
- if ((typeof argument === 'string' || argStr === '[object String]') && typeof console !== 'undefined') {
2792
- // eslint-disable-next-line no-console
2793
- console.warn("Starting with v2.0.0-beta.1 date-fns doesn't accept strings as date arguments. Please use `parseISO` to parse strings. See: https://github.com/date-fns/date-fns/blob/master/docs/upgradeGuide.md#string-arguments");
2794
- // eslint-disable-next-line no-console
2795
- console.warn(new Error().stack);
2796
- }
2797
- return new Date(NaN);
2798
- }
2853
+ function toDate(argument, context) {
2854
+ // [TODO] Get rid of `toDate` or `constructFrom`?
2855
+ return constructFrom(argument, argument);
2799
2856
  }
2800
2857
 
2858
+ /**
2859
+ * The {@link addDays} function options.
2860
+ */
2861
+
2801
2862
  /**
2802
2863
  * @name addDays
2803
2864
  * @category Day Helpers
@@ -2806,31 +2867,34 @@ function toDate(argument) {
2806
2867
  * @description
2807
2868
  * Add the specified number of days to the given date.
2808
2869
  *
2809
- * @param {Date|Number} date - the date to be changed
2810
- * @param {Number} amount - the amount of days to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
2811
- * @returns {Date} - the new date with the days added
2812
- * @throws {TypeError} - 2 arguments required
2870
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
2871
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
2872
+ *
2873
+ * @param date - The date to be changed
2874
+ * @param amount - The amount of days to be added.
2875
+ * @param options - An object with options
2876
+ *
2877
+ * @returns The new date with the days added
2813
2878
  *
2814
2879
  * @example
2815
2880
  * // Add 10 days to 1 September 2014:
2816
2881
  * const result = addDays(new Date(2014, 8, 1), 10)
2817
2882
  * //=> Thu Sep 11 2014 00:00:00
2818
2883
  */
2819
- function addDays(dirtyDate, dirtyAmount) {
2820
- requiredArgs(2, arguments);
2821
- var date = toDate(dirtyDate);
2822
- var amount = toInteger(dirtyAmount);
2823
- if (isNaN(amount)) {
2824
- return new Date(NaN);
2825
- }
2826
- if (!amount) {
2827
- // If 0 days, no-op to avoid changing times in the hour before end of DST
2828
- return date;
2829
- }
2830
- date.setDate(date.getDate() + amount);
2831
- return date;
2884
+ function addDays(date, amount, options) {
2885
+ const _date = toDate(date);
2886
+ if (isNaN(amount)) return constructFrom(date, NaN);
2887
+
2888
+ // If 0 days, no-op to avoid changing times in the hour before end of DST
2889
+ if (!amount) return _date;
2890
+ _date.setDate(_date.getDate() + amount);
2891
+ return _date;
2832
2892
  }
2833
2893
 
2894
+ /**
2895
+ * The {@link addMonths} function options.
2896
+ */
2897
+
2834
2898
  /**
2835
2899
  * @name addMonths
2836
2900
  * @category Month Helpers
@@ -2839,28 +2903,32 @@ function addDays(dirtyDate, dirtyAmount) {
2839
2903
  * @description
2840
2904
  * Add the specified number of months to the given date.
2841
2905
  *
2842
- * @param {Date|Number} date - the date to be changed
2843
- * @param {Number} amount - the amount of months to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
2844
- * @returns {Date} the new date with the months added
2845
- * @throws {TypeError} 2 arguments required
2906
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
2907
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
2908
+ *
2909
+ * @param date - The date to be changed
2910
+ * @param amount - The amount of months to be added.
2911
+ * @param options - The options object
2912
+ *
2913
+ * @returns The new date with the months added
2846
2914
  *
2847
2915
  * @example
2848
2916
  * // Add 5 months to 1 September 2014:
2849
2917
  * const result = addMonths(new Date(2014, 8, 1), 5)
2850
2918
  * //=> Sun Feb 01 2015 00:00:00
2919
+ *
2920
+ * // Add one month to 30 January 2023:
2921
+ * const result = addMonths(new Date(2023, 0, 30), 1)
2922
+ * //=> Tue Feb 28 2023 00:00:00
2851
2923
  */
2852
- function addMonths(dirtyDate, dirtyAmount) {
2853
- requiredArgs(2, arguments);
2854
- var date = toDate(dirtyDate);
2855
- var amount = toInteger(dirtyAmount);
2856
- if (isNaN(amount)) {
2857
- return new Date(NaN);
2858
- }
2924
+ function addMonths(date, amount, options) {
2925
+ const _date = toDate(date);
2926
+ if (isNaN(amount)) return constructFrom(date, NaN);
2859
2927
  if (!amount) {
2860
2928
  // If 0 months, no-op to avoid changing times in the hour before end of DST
2861
- return date;
2929
+ return _date;
2862
2930
  }
2863
- var dayOfMonth = date.getDate();
2931
+ const dayOfMonth = _date.getDate();
2864
2932
 
2865
2933
  // The JS Date object supports date math by accepting out-of-bounds values for
2866
2934
  // month, day, etc. For example, new Date(2020, 0, 0) returns 31 Dec 2019 and
@@ -2870,9 +2938,9 @@ function addMonths(dirtyDate, dirtyAmount) {
2870
2938
  // we'll default to the end of the desired month by adding 1 to the desired
2871
2939
  // month and using a date of 0 to back up one day to the end of the desired
2872
2940
  // month.
2873
- var endOfDesiredMonth = new Date(date.getTime());
2874
- endOfDesiredMonth.setMonth(date.getMonth() + amount + 1, 0);
2875
- var daysInMonth = endOfDesiredMonth.getDate();
2941
+ const endOfDesiredMonth = constructFrom(date, _date.getTime());
2942
+ endOfDesiredMonth.setMonth(_date.getMonth() + amount + 1, 0);
2943
+ const daysInMonth = endOfDesiredMonth.getDate();
2876
2944
  if (dayOfMonth >= daysInMonth) {
2877
2945
  // If we're already at the end of the month, then this is the correct date
2878
2946
  // and we're done.
@@ -2885,15 +2953,19 @@ function addMonths(dirtyDate, dirtyAmount) {
2885
2953
  // the last day of the month and its local time was in the hour skipped or
2886
2954
  // repeated next to a DST transition. So we use `date` instead which is
2887
2955
  // guaranteed to still have the original time.
2888
- date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);
2889
- return date;
2956
+ _date.setFullYear(endOfDesiredMonth.getFullYear(), endOfDesiredMonth.getMonth(), dayOfMonth);
2957
+ return _date;
2890
2958
  }
2891
2959
  }
2892
- var defaultOptions = {};
2960
+ let defaultOptions = {};
2893
2961
  function getDefaultOptions() {
2894
2962
  return defaultOptions;
2895
2963
  }
2896
2964
 
2965
+ /**
2966
+ * The {@link startOfWeek} function options.
2967
+ */
2968
+
2897
2969
  /**
2898
2970
  * @name startOfWeek
2899
2971
  * @category Week Helpers
@@ -2903,13 +2975,13 @@ function getDefaultOptions() {
2903
2975
  * Return the start of a week for the given date.
2904
2976
  * The result will be in the local timezone.
2905
2977
  *
2906
- * @param {Date|Number} date - the original date
2907
- * @param {Object} [options] - an object with options.
2908
- * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
2909
- * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
2910
- * @returns {Date} the start of a week
2911
- * @throws {TypeError} 1 argument required
2912
- * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
2978
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
2979
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
2980
+ *
2981
+ * @param date - The original date
2982
+ * @param options - An object with options
2983
+ *
2984
+ * @returns The start of a week
2913
2985
  *
2914
2986
  * @example
2915
2987
  * // The start of a week for 2 September 2014 11:55:00:
@@ -2921,24 +2993,28 @@ function getDefaultOptions() {
2921
2993
  * const result = startOfWeek(new Date(2014, 8, 2, 11, 55, 0), { weekStartsOn: 1 })
2922
2994
  * //=> Mon Sep 01 2014 00:00:00
2923
2995
  */
2924
- function startOfWeek(dirtyDate, options) {
2925
- var _ref, _ref2, _ref3, _options$weekStartsOn, _defaultOptions$local, _defaultOptions$local2;
2926
- requiredArgs(1, arguments);
2927
- var defaultOptions = getDefaultOptions();
2928
- var weekStartsOn = toInteger((_ref = (_ref2 = (_ref3 = (_options$weekStartsOn = void 0) !== null && _options$weekStartsOn !== void 0 ? _options$weekStartsOn : void 0) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.weekStartsOn) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.weekStartsOn) !== null && _ref !== void 0 ? _ref : 0);
2929
-
2930
- // Test if weekStartsOn is between 0 and 6 _and_ is not NaN
2931
- if (!(weekStartsOn >= 0 && weekStartsOn <= 6)) {
2932
- throw new RangeError('weekStartsOn must be between 0 and 6 inclusively');
2996
+ function startOfWeek(date, options) {
2997
+ const defaultOptions = getDefaultOptions();
2998
+ const weekStartsOn = defaultOptions.weekStartsOn ?? defaultOptions.locale?.options?.weekStartsOn ?? 0;
2999
+ const _date = toDate(date);
3000
+ const day = _date.getDay();
3001
+ const diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
3002
+ _date.setDate(_date.getDate() - diff);
3003
+ _date.setHours(0, 0, 0, 0);
3004
+ return _date;
3005
+ }
3006
+ function normalizeDates(context) {
3007
+ for (var _len = arguments.length, dates = new Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {
3008
+ dates[_key - 1] = arguments[_key];
2933
3009
  }
2934
- var date = toDate(dirtyDate);
2935
- var day = date.getDay();
2936
- var diff = (day < weekStartsOn ? 7 : 0) + day - weekStartsOn;
2937
- date.setDate(date.getDate() - diff);
2938
- date.setHours(0, 0, 0, 0);
2939
- return date;
3010
+ const normalize = constructFrom.bind(null, dates.find(date => typeof date === "object"));
3011
+ return dates.map(normalize);
2940
3012
  }
2941
3013
 
3014
+ /**
3015
+ * The {@link startOfDay} function options.
3016
+ */
3017
+
2942
3018
  /**
2943
3019
  * @name startOfDay
2944
3020
  * @category Day Helpers
@@ -2948,47 +3024,59 @@ function startOfWeek(dirtyDate, options) {
2948
3024
  * Return the start of a day for the given date.
2949
3025
  * The result will be in the local timezone.
2950
3026
  *
2951
- * @param {Date|Number} date - the original date
2952
- * @returns {Date} the start of a day
2953
- * @throws {TypeError} 1 argument required
3027
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3028
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
3029
+ *
3030
+ * @param date - The original date
3031
+ * @param options - The options
3032
+ *
3033
+ * @returns The start of a day
2954
3034
  *
2955
3035
  * @example
2956
3036
  * // The start of a day for 2 September 2014 11:55:00:
2957
3037
  * const result = startOfDay(new Date(2014, 8, 2, 11, 55, 0))
2958
3038
  * //=> Tue Sep 02 2014 00:00:00
2959
3039
  */
2960
- function startOfDay(dirtyDate) {
2961
- requiredArgs(1, arguments);
2962
- var date = toDate(dirtyDate);
2963
- date.setHours(0, 0, 0, 0);
2964
- return date;
3040
+ function startOfDay(date, options) {
3041
+ const _date = toDate(date);
3042
+ _date.setHours(0, 0, 0, 0);
3043
+ return _date;
2965
3044
  }
2966
3045
 
3046
+ /**
3047
+ * The {@link addWeeks} function options.
3048
+ */
3049
+
2967
3050
  /**
2968
3051
  * @name addWeeks
2969
3052
  * @category Week Helpers
2970
3053
  * @summary Add the specified number of weeks to the given date.
2971
3054
  *
2972
3055
  * @description
2973
- * Add the specified number of week to the given date.
3056
+ * Add the specified number of weeks to the given date.
3057
+ *
3058
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3059
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
2974
3060
  *
2975
- * @param {Date|Number} date - the date to be changed
2976
- * @param {Number} amount - the amount of weeks to be added. Positive decimals will be rounded using `Math.floor`, decimals less than zero will be rounded using `Math.ceil`.
2977
- * @returns {Date} the new date with the weeks added
2978
- * @throws {TypeError} 2 arguments required
3061
+ * @param date - The date to be changed
3062
+ * @param amount - The amount of weeks to be added.
3063
+ * @param options - An object with options
3064
+ *
3065
+ * @returns The new date with the weeks added
2979
3066
  *
2980
3067
  * @example
2981
3068
  * // Add 4 weeks to 1 September 2014:
2982
3069
  * const result = addWeeks(new Date(2014, 8, 1), 4)
2983
3070
  * //=> Mon Sep 29 2014 00:00:00
2984
3071
  */
2985
- function addWeeks(dirtyDate, dirtyAmount) {
2986
- requiredArgs(2, arguments);
2987
- var amount = toInteger(dirtyAmount);
2988
- var days = amount * 7;
2989
- return addDays(dirtyDate, days);
3072
+ function addWeeks(date, amount, options) {
3073
+ return addDays(date, amount * 7);
2990
3074
  }
2991
3075
 
3076
+ /**
3077
+ * The {@link isSameDay} function options.
3078
+ */
3079
+
2992
3080
  /**
2993
3081
  * @name isSameDay
2994
3082
  * @category Day Helpers
@@ -2997,10 +3085,11 @@ function addWeeks(dirtyDate, dirtyAmount) {
2997
3085
  * @description
2998
3086
  * Are the given dates in the same day (and year and month)?
2999
3087
  *
3000
- * @param {Date|Number} dateLeft - the first date to check
3001
- * @param {Date|Number} dateRight - the second date to check
3002
- * @returns {Boolean} the dates are in the same day (and year and month)
3003
- * @throws {TypeError} 2 arguments required
3088
+ * @param laterDate - The first date to check
3089
+ * @param earlierDate - The second date to check
3090
+ * @param options - An object with options
3091
+ *
3092
+ * @returns The dates are in the same day (and year and month)
3004
3093
  *
3005
3094
  * @example
3006
3095
  * // Are 4 September 06:00:00 and 4 September 18:00:00 in the same day?
@@ -3017,13 +3106,28 @@ function addWeeks(dirtyDate, dirtyAmount) {
3017
3106
  * const result = isSameDay(new Date(2014, 8, 4), new Date(2015, 8, 4))
3018
3107
  * //=> false
3019
3108
  */
3020
- function isSameDay(dirtyDateLeft, dirtyDateRight) {
3021
- requiredArgs(2, arguments);
3022
- var dateLeftStartOfDay = startOfDay(dirtyDateLeft);
3023
- var dateRightStartOfDay = startOfDay(dirtyDateRight);
3024
- return dateLeftStartOfDay.getTime() === dateRightStartOfDay.getTime();
3109
+ function isSameDay(laterDate, earlierDate, options) {
3110
+ const [dateLeft_, dateRight_] = normalizeDates(options?.in, laterDate, earlierDate);
3111
+ return +startOfDay(dateLeft_) === +startOfDay(dateRight_);
3112
+ }
3113
+ function normalizeInterval(context, interval) {
3114
+ const [start, end] = normalizeDates(context, interval.start, interval.end);
3115
+ return {
3116
+ start,
3117
+ end
3118
+ };
3025
3119
  }
3026
3120
 
3121
+ /**
3122
+ * The {@link eachWeekOfInterval} function options.
3123
+ */
3124
+
3125
+ /**
3126
+ * The {@link eachWeekOfInterval} function result type. It resolves the proper data type.
3127
+ * It uses the first argument date object type, starting from the interval start date,
3128
+ * then the end interval date. If a context function is passed, it uses the context function return type.
3129
+ */
3130
+
3027
3131
  /**
3028
3132
  * @name eachWeekOfInterval
3029
3133
  * @category Interval Helpers
@@ -3032,15 +3136,10 @@ function isSameDay(dirtyDateLeft, dirtyDateRight) {
3032
3136
  * @description
3033
3137
  * Return the array of weeks within the specified time interval.
3034
3138
  *
3035
- * @param {Interval} interval - the interval. See [Interval]{@link https://date-fns.org/docs/Interval}
3036
- * @param {Object} [options] - an object with options.
3037
- * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
3038
- * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
3039
- * @returns {Date[]} the array with starts of weeks from the week of the interval start to the week of the interval end
3040
- * @throws {TypeError} 1 argument required
3041
- * @throws {RangeError} `options.weekStartsOn` must be 0, 1, ..., 6
3042
- * @throws {RangeError} The start of an interval cannot be after its end
3043
- * @throws {RangeError} Date in interval cannot be `Invalid Date`
3139
+ * @param interval - The interval.
3140
+ * @param options - An object with options.
3141
+ *
3142
+ * @returns The array with starts of weeks from the week of the interval start to the week of the interval end
3044
3143
  *
3045
3144
  * @example
3046
3145
  * // Each week within interval 6 October 2014 - 23 November 2014:
@@ -3059,88 +3158,66 @@ function isSameDay(dirtyDateLeft, dirtyDateRight) {
3059
3158
  * // Sun Nov 23 2014 00:00:00
3060
3159
  * // ]
3061
3160
  */
3062
- function eachWeekOfInterval(dirtyInterval, options) {
3063
- requiredArgs(1, arguments);
3064
- var interval = dirtyInterval || {};
3065
- var startDate = toDate(interval.start);
3066
- var endDate = toDate(interval.end);
3067
- var endTime = endDate.getTime();
3068
-
3069
- // Throw an exception if start date is after end date or if any date is `Invalid Date`
3070
- if (!(startDate.getTime() <= endTime)) {
3071
- throw new RangeError('Invalid interval');
3072
- }
3073
- var startDateWeek = startOfWeek(startDate, options);
3074
- var endDateWeek = startOfWeek(endDate, options);
3075
-
3076
- // Some timezones switch DST at midnight, making start of day unreliable in these timezones, 3pm is a safe bet
3161
+ function eachWeekOfInterval(interval, options) {
3162
+ const {
3163
+ start,
3164
+ end
3165
+ } = normalizeInterval(options?.in, interval);
3166
+ let reversed = +start > +end;
3167
+ const startDateWeek = reversed ? startOfWeek(end) : startOfWeek(start);
3168
+ const endDateWeek = reversed ? startOfWeek(start) : startOfWeek(end);
3077
3169
  startDateWeek.setHours(15);
3078
3170
  endDateWeek.setHours(15);
3079
- endTime = endDateWeek.getTime();
3080
- var weeks = [];
3081
- var currentWeek = startDateWeek;
3082
- while (currentWeek.getTime() <= endTime) {
3083
- currentWeek.setHours(0);
3084
- weeks.push(toDate(currentWeek));
3085
- currentWeek = addWeeks(currentWeek, 1);
3086
- currentWeek.setHours(15);
3171
+ const endTime = +endDateWeek.getTime();
3172
+ let currentDate = startDateWeek;
3173
+ let step = 1;
3174
+ const dates = [];
3175
+ while (+currentDate <= endTime) {
3176
+ currentDate.setHours(0);
3177
+ dates.push(constructFrom(start, currentDate));
3178
+ currentDate = addWeeks(currentDate, step);
3179
+ currentDate.setHours(15);
3087
3180
  }
3088
- return weeks;
3181
+ return reversed ? dates.reverse() : dates;
3089
3182
  }
3090
3183
 
3184
+ /**
3185
+ * The {@link startOfMonth} function options.
3186
+ */
3187
+
3091
3188
  /**
3092
3189
  * @name startOfMonth
3093
3190
  * @category Month Helpers
3094
3191
  * @summary Return the start of a month for the given date.
3095
3192
  *
3096
3193
  * @description
3097
- * Return the start of a month for the given date.
3098
- * The result will be in the local timezone.
3194
+ * Return the start of a month for the given date. The result will be in the local timezone.
3099
3195
  *
3100
- * @param {Date|Number} date - the original date
3101
- * @returns {Date} the start of a month
3102
- * @throws {TypeError} 1 argument required
3196
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments.
3197
+ * Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3198
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed,
3199
+ * or inferred from the arguments.
3200
+ *
3201
+ * @param date - The original date
3202
+ * @param options - An object with options
3203
+ *
3204
+ * @returns The start of a month
3103
3205
  *
3104
3206
  * @example
3105
3207
  * // The start of a month for 2 September 2014 11:55:00:
3106
3208
  * const result = startOfMonth(new Date(2014, 8, 2, 11, 55, 0))
3107
3209
  * //=> Mon Sep 01 2014 00:00:00
3108
3210
  */
3109
- function startOfMonth(dirtyDate) {
3110
- requiredArgs(1, arguments);
3111
- var date = toDate(dirtyDate);
3112
- date.setDate(1);
3113
- date.setHours(0, 0, 0, 0);
3114
- return date;
3211
+ function startOfMonth(date, options) {
3212
+ const _date = toDate(date);
3213
+ _date.setDate(1);
3214
+ _date.setHours(0, 0, 0, 0);
3215
+ return _date;
3115
3216
  }
3116
3217
 
3117
3218
  /**
3118
- * @name getDaysInMonth
3119
- * @category Month Helpers
3120
- * @summary Get the number of days in a month of the given date.
3121
- *
3122
- * @description
3123
- * Get the number of days in a month of the given date.
3124
- *
3125
- * @param {Date|Number} date - the given date
3126
- * @returns {Number} the number of days in a month
3127
- * @throws {TypeError} 1 argument required
3128
- *
3129
- * @example
3130
- * // How many days are in February 2000?
3131
- * const result = getDaysInMonth(new Date(2000, 1))
3132
- * //=> 29
3219
+ * The {@link getWeekYear} function options.
3133
3220
  */
3134
- function getDaysInMonth(dirtyDate) {
3135
- requiredArgs(1, arguments);
3136
- var date = toDate(dirtyDate);
3137
- var year = date.getFullYear();
3138
- var monthIndex = date.getMonth();
3139
- var lastDayOfMonth = new Date(0);
3140
- lastDayOfMonth.setFullYear(year, monthIndex + 1, 0);
3141
- lastDayOfMonth.setHours(0, 0, 0, 0);
3142
- return lastDayOfMonth.getDate();
3143
- }
3144
3221
 
3145
3222
  /**
3146
3223
  * @name getWeekYear
@@ -3154,17 +3231,12 @@ function getDaysInMonth(dirtyDate) {
3154
3231
  * and `options.firstWeekContainsDate` (which is the day of January, which is always in
3155
3232
  * the first week of the week-numbering year)
3156
3233
  *
3157
- * Week numbering: https://en.wikipedia.org/wiki/Week#Week_numbering
3234
+ * Week numbering: https://en.wikipedia.org/wiki/Week#The_ISO_week_date_system
3235
+ *
3236
+ * @param date - The given date
3237
+ * @param options - An object with options.
3158
3238
  *
3159
- * @param {Date|Number} date - the given date
3160
- * @param {Object} [options] - an object with options.
3161
- * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
3162
- * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
3163
- * @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
3164
- * @returns {Number} the local week-numbering year
3165
- * @throws {TypeError} 1 argument required
3166
- * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
3167
- * @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
3239
+ * @returns The local week-numbering year
3168
3240
  *
3169
3241
  * @example
3170
3242
  * // Which week numbering year is 26 December 2004 with the default settings?
@@ -3181,35 +3253,32 @@ function getDaysInMonth(dirtyDate) {
3181
3253
  * const result = getWeekYear(new Date(2004, 11, 26), { firstWeekContainsDate: 4 })
3182
3254
  * //=> 2004
3183
3255
  */
3184
- function getWeekYear(dirtyDate, options) {
3185
- var _ref, _ref2, _ref3, _options$firstWeekCon, _defaultOptions$local, _defaultOptions$local2;
3186
- requiredArgs(1, arguments);
3187
- var date = toDate(dirtyDate);
3188
- var year = date.getFullYear();
3189
- var defaultOptions = getDefaultOptions();
3190
- var firstWeekContainsDate = toInteger((_ref = (_ref2 = (_ref3 = (_options$firstWeekCon = void 0) !== null && _options$firstWeekCon !== void 0 ? _options$firstWeekCon : void 0) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.firstWeekContainsDate) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.firstWeekContainsDate) !== null && _ref !== void 0 ? _ref : 1);
3191
-
3192
- // Test if weekStartsOn is between 1 and 7 _and_ is not NaN
3193
- if (!(firstWeekContainsDate >= 1 && firstWeekContainsDate <= 7)) {
3194
- throw new RangeError('firstWeekContainsDate must be between 1 and 7 inclusively');
3195
- }
3196
- var firstWeekOfNextYear = new Date(0);
3256
+ function getWeekYear(date, options) {
3257
+ const _date = toDate(date);
3258
+ const year = _date.getFullYear();
3259
+ const defaultOptions = getDefaultOptions();
3260
+ const firstWeekContainsDate = defaultOptions.firstWeekContainsDate ?? defaultOptions.locale?.options?.firstWeekContainsDate ?? 1;
3261
+ const firstWeekOfNextYear = constructFrom(date, 0);
3197
3262
  firstWeekOfNextYear.setFullYear(year + 1, 0, firstWeekContainsDate);
3198
3263
  firstWeekOfNextYear.setHours(0, 0, 0, 0);
3199
- var startOfNextYear = startOfWeek(firstWeekOfNextYear, options);
3200
- var firstWeekOfThisYear = new Date(0);
3264
+ const startOfNextYear = startOfWeek(firstWeekOfNextYear);
3265
+ const firstWeekOfThisYear = constructFrom(date, 0);
3201
3266
  firstWeekOfThisYear.setFullYear(year, 0, firstWeekContainsDate);
3202
3267
  firstWeekOfThisYear.setHours(0, 0, 0, 0);
3203
- var startOfThisYear = startOfWeek(firstWeekOfThisYear, options);
3204
- if (date.getTime() >= startOfNextYear.getTime()) {
3268
+ const startOfThisYear = startOfWeek(firstWeekOfThisYear);
3269
+ if (+_date >= +startOfNextYear) {
3205
3270
  return year + 1;
3206
- } else if (date.getTime() >= startOfThisYear.getTime()) {
3271
+ } else if (+_date >= +startOfThisYear) {
3207
3272
  return year;
3208
3273
  } else {
3209
3274
  return year - 1;
3210
3275
  }
3211
3276
  }
3212
3277
 
3278
+ /**
3279
+ * The {@link startOfWeekYear} function options.
3280
+ */
3281
+
3213
3282
  /**
3214
3283
  * @name startOfWeekYear
3215
3284
  * @category Week-Numbering Year Helpers
@@ -3222,17 +3291,15 @@ function getWeekYear(dirtyDate, options) {
3222
3291
  * and `options.firstWeekContainsDate` (which is the day of January, which is always in
3223
3292
  * the first week of the week-numbering year)
3224
3293
  *
3225
- * Week numbering: https://en.wikipedia.org/wiki/Week#Week_numbering
3294
+ * Week numbering: https://en.wikipedia.org/wiki/Week#The_ISO_week_date_system
3295
+ *
3296
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3297
+ * @typeParam ResultDate - The result `Date` type.
3226
3298
  *
3227
- * @param {Date|Number} date - the original date
3228
- * @param {Object} [options] - an object with options.
3229
- * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
3230
- * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
3231
- * @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
3232
- * @returns {Date} the start of a week-numbering year
3233
- * @throws {TypeError} 1 argument required
3234
- * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
3235
- * @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
3299
+ * @param date - The original date
3300
+ * @param options - An object with options
3301
+ *
3302
+ * @returns The start of a week-numbering year
3236
3303
  *
3237
3304
  * @example
3238
3305
  * // The start of an a week-numbering year for 2 July 2005 with default settings:
@@ -3249,19 +3316,20 @@ function getWeekYear(dirtyDate, options) {
3249
3316
  * })
3250
3317
  * //=> Mon Jan 03 2005 00:00:00
3251
3318
  */
3252
- function startOfWeekYear(dirtyDate, options) {
3253
- var _ref, _ref2, _ref3, _options$firstWeekCon, _defaultOptions$local, _defaultOptions$local2;
3254
- requiredArgs(1, arguments);
3255
- var defaultOptions = getDefaultOptions();
3256
- var firstWeekContainsDate = toInteger((_ref = (_ref2 = (_ref3 = (_options$firstWeekCon = void 0) !== null && _options$firstWeekCon !== void 0 ? _options$firstWeekCon : void 0) !== null && _ref3 !== void 0 ? _ref3 : defaultOptions.firstWeekContainsDate) !== null && _ref2 !== void 0 ? _ref2 : (_defaultOptions$local = defaultOptions.locale) === null || _defaultOptions$local === void 0 ? void 0 : (_defaultOptions$local2 = _defaultOptions$local.options) === null || _defaultOptions$local2 === void 0 ? void 0 : _defaultOptions$local2.firstWeekContainsDate) !== null && _ref !== void 0 ? _ref : 1);
3257
- var year = getWeekYear(dirtyDate, options);
3258
- var firstWeek = new Date(0);
3319
+ function startOfWeekYear(date, options) {
3320
+ const defaultOptions = getDefaultOptions();
3321
+ const firstWeekContainsDate = defaultOptions.firstWeekContainsDate ?? defaultOptions.locale?.options?.firstWeekContainsDate ?? 1;
3322
+ const year = getWeekYear(date);
3323
+ const firstWeek = constructFrom(date, 0);
3259
3324
  firstWeek.setFullYear(year, 0, firstWeekContainsDate);
3260
3325
  firstWeek.setHours(0, 0, 0, 0);
3261
- var date = startOfWeek(firstWeek, options);
3262
- return date;
3326
+ const _date = startOfWeek(firstWeek);
3327
+ return _date;
3263
3328
  }
3264
- var MILLISECONDS_IN_WEEK = 604800000;
3329
+
3330
+ /**
3331
+ * The {@link getWeek} function options.
3332
+ */
3265
3333
 
3266
3334
  /**
3267
3335
  * @name getWeek
@@ -3275,23 +3343,19 @@ var MILLISECONDS_IN_WEEK = 604800000;
3275
3343
  * and `options.firstWeekContainsDate` (which is the day of January, which is always in
3276
3344
  * the first week of the week-numbering year)
3277
3345
  *
3278
- * Week numbering: https://en.wikipedia.org/wiki/Week#Week_numbering
3346
+ * Week numbering: https://en.wikipedia.org/wiki/Week#The_ISO_week_date_system
3347
+ *
3348
+ * @param date - The given date
3349
+ * @param options - An object with options
3279
3350
  *
3280
- * @param {Date|Number} date - the given date
3281
- * @param {Object} [options] - an object with options.
3282
- * @param {Locale} [options.locale=defaultLocale] - the locale object. See [Locale]{@link https://date-fns.org/docs/Locale}
3283
- * @param {0|1|2|3|4|5|6} [options.weekStartsOn=0] - the index of the first day of the week (0 - Sunday)
3284
- * @param {1|2|3|4|5|6|7} [options.firstWeekContainsDate=1] - the day of January, which is always in the first week of the year
3285
- * @returns {Number} the week
3286
- * @throws {TypeError} 1 argument required
3287
- * @throws {RangeError} `options.weekStartsOn` must be between 0 and 6
3288
- * @throws {RangeError} `options.firstWeekContainsDate` must be between 1 and 7
3351
+ * @returns The week
3289
3352
  *
3290
3353
  * @example
3291
3354
  * // Which week of the local week numbering year is 2 January 2005 with default options?
3292
3355
  * const result = getWeek(new Date(2005, 0, 2))
3293
3356
  * //=> 2
3294
3357
  *
3358
+ * @example
3295
3359
  * // Which week of the local week numbering year is 2 January 2005,
3296
3360
  * // if Monday is the first day of the week,
3297
3361
  * // and the first week of the year always contains 4 January?
@@ -3301,18 +3365,52 @@ var MILLISECONDS_IN_WEEK = 604800000;
3301
3365
  * })
3302
3366
  * //=> 53
3303
3367
  */
3368
+ function getWeek(date, options) {
3369
+ const _date = toDate(date);
3370
+ const diff = +startOfWeek(_date) - +startOfWeekYear(_date);
3304
3371
 
3305
- function getWeek(dirtyDate, options) {
3306
- requiredArgs(1, arguments);
3307
- var date = toDate(dirtyDate);
3308
- var diff = startOfWeek(date, options).getTime() - startOfWeekYear(date, options).getTime();
3372
+ // Round the number of weeks to the nearest integer because the number of
3373
+ // milliseconds in a week is not constant (e.g. it's different in the week of
3374
+ // the daylight saving time clock shift).
3375
+ return Math.round(diff / millisecondsInWeek) + 1;
3376
+ }
3309
3377
 
3310
- // Round the number of days to the nearest integer
3311
- // because the number of milliseconds in a week is not constant
3312
- // (e.g. it's different in the week of the daylight saving time clock shift)
3313
- return Math.round(diff / MILLISECONDS_IN_WEEK) + 1;
3378
+ /**
3379
+ * The {@link getDaysInMonth} function options.
3380
+ */
3381
+
3382
+ /**
3383
+ * @name getDaysInMonth
3384
+ * @category Month Helpers
3385
+ * @summary Get the number of days in a month of the given date.
3386
+ *
3387
+ * @description
3388
+ * Get the number of days in a month of the given date, considering the context if provided.
3389
+ *
3390
+ * @param date - The given date
3391
+ * @param options - An object with options
3392
+ *
3393
+ * @returns The number of days in a month
3394
+ *
3395
+ * @example
3396
+ * // How many days are in February 2000?
3397
+ * const result = getDaysInMonth(new Date(2000, 1))
3398
+ * //=> 29
3399
+ */
3400
+ function getDaysInMonth(date, options) {
3401
+ const _date = toDate(date);
3402
+ const year = _date.getFullYear();
3403
+ const monthIndex = _date.getMonth();
3404
+ const lastDayOfMonth = constructFrom(_date, 0);
3405
+ lastDayOfMonth.setFullYear(year, monthIndex + 1, 0);
3406
+ lastDayOfMonth.setHours(0, 0, 0, 0);
3407
+ return lastDayOfMonth.getDate();
3314
3408
  }
3315
3409
 
3410
+ /**
3411
+ * The {@link lastDayOfMonth} function options.
3412
+ */
3413
+
3316
3414
  /**
3317
3415
  * @name lastDayOfMonth
3318
3416
  * @category Month Helpers
@@ -3322,24 +3420,31 @@ function getWeek(dirtyDate, options) {
3322
3420
  * Return the last day of a month for the given date.
3323
3421
  * The result will be in the local timezone.
3324
3422
  *
3325
- * @param {Date|Number} date - the original date
3326
- * @returns {Date} the last day of a month
3327
- * @throws {TypeError} 1 argument required
3423
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3424
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
3425
+ *
3426
+ * @param date - The original date
3427
+ * @param options - An object with options
3428
+ *
3429
+ * @returns The last day of a month
3328
3430
  *
3329
3431
  * @example
3330
3432
  * // The last day of a month for 2 September 2014 11:55:00:
3331
3433
  * const result = lastDayOfMonth(new Date(2014, 8, 2, 11, 55, 0))
3332
3434
  * //=> Tue Sep 30 2014 00:00:00
3333
3435
  */
3334
- function lastDayOfMonth(dirtyDate) {
3335
- requiredArgs(1, arguments);
3336
- var date = toDate(dirtyDate);
3337
- var month = date.getMonth();
3338
- date.setFullYear(date.getFullYear(), month + 1, 0);
3339
- date.setHours(0, 0, 0, 0);
3340
- return date;
3436
+ function lastDayOfMonth(date, options) {
3437
+ const _date = toDate(date);
3438
+ const month = _date.getMonth();
3439
+ _date.setFullYear(_date.getFullYear(), month + 1, 0);
3440
+ _date.setHours(0, 0, 0, 0);
3441
+ return toDate(_date);
3341
3442
  }
3342
3443
 
3444
+ /**
3445
+ * The {@link isSameMonth} function options.
3446
+ */
3447
+
3343
3448
  /**
3344
3449
  * @name isSameMonth
3345
3450
  * @category Month Helpers
@@ -3348,10 +3453,11 @@ function lastDayOfMonth(dirtyDate) {
3348
3453
  * @description
3349
3454
  * Are the given dates in the same month (and year)?
3350
3455
  *
3351
- * @param {Date|Number} dateLeft - the first date to check
3352
- * @param {Date|Number} dateRight - the second date to check
3353
- * @returns {Boolean} the dates are in the same month (and year)
3354
- * @throws {TypeError} 2 arguments required
3456
+ * @param laterDate - The first date to check
3457
+ * @param earlierDate - The second date to check
3458
+ * @param options - An object with options
3459
+ *
3460
+ * @returns The dates are in the same month (and year)
3355
3461
  *
3356
3462
  * @example
3357
3463
  * // Are 2 September 2014 and 25 September 2014 in the same month?
@@ -3363,13 +3469,15 @@ function lastDayOfMonth(dirtyDate) {
3363
3469
  * const result = isSameMonth(new Date(2014, 8, 2), new Date(2015, 8, 25))
3364
3470
  * //=> false
3365
3471
  */
3366
- function isSameMonth(dirtyDateLeft, dirtyDateRight) {
3367
- requiredArgs(2, arguments);
3368
- var dateLeft = toDate(dirtyDateLeft);
3369
- var dateRight = toDate(dirtyDateRight);
3370
- return dateLeft.getFullYear() === dateRight.getFullYear() && dateLeft.getMonth() === dateRight.getMonth();
3472
+ function isSameMonth(laterDate, earlierDate, options) {
3473
+ const [laterDate_, earlierDate_] = normalizeDates(options?.in, laterDate, earlierDate);
3474
+ return laterDate_.getFullYear() === earlierDate_.getFullYear() && laterDate_.getMonth() === earlierDate_.getMonth();
3371
3475
  }
3372
3476
 
3477
+ /**
3478
+ * The {@link setMonth} function options.
3479
+ */
3480
+
3373
3481
  /**
3374
3482
  * @name setMonth
3375
3483
  * @category Month Helpers
@@ -3378,32 +3486,38 @@ function isSameMonth(dirtyDateLeft, dirtyDateRight) {
3378
3486
  * @description
3379
3487
  * Set the month to the given date.
3380
3488
  *
3381
- * @param {Date|Number} date - the date to be changed
3382
- * @param {Number} month - the month of the new date
3383
- * @returns {Date} the new date with the month set
3384
- * @throws {TypeError} 2 arguments required
3489
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3490
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
3491
+ *
3492
+ * @param date - The date to be changed
3493
+ * @param month - The month index to set (0-11)
3494
+ * @param options - The options
3495
+ *
3496
+ * @returns The new date with the month set
3385
3497
  *
3386
3498
  * @example
3387
3499
  * // Set February to 1 September 2014:
3388
3500
  * const result = setMonth(new Date(2014, 8, 1), 1)
3389
3501
  * //=> Sat Feb 01 2014 00:00:00
3390
3502
  */
3391
- function setMonth(dirtyDate, dirtyMonth) {
3392
- requiredArgs(2, arguments);
3393
- var date = toDate(dirtyDate);
3394
- var month = toInteger(dirtyMonth);
3395
- var year = date.getFullYear();
3396
- var day = date.getDate();
3397
- var dateWithDesiredMonth = new Date(0);
3398
- dateWithDesiredMonth.setFullYear(year, month, 15);
3399
- dateWithDesiredMonth.setHours(0, 0, 0, 0);
3400
- var daysInMonth = getDaysInMonth(dateWithDesiredMonth);
3401
- // Set the last day of the new month
3402
- // if the original date was the last day of the longer month
3403
- date.setMonth(month, Math.min(day, daysInMonth));
3404
- return date;
3503
+ function setMonth(date, month, options) {
3504
+ const _date = toDate(date);
3505
+ const year = _date.getFullYear();
3506
+ const day = _date.getDate();
3507
+ const midMonth = constructFrom(date, 0);
3508
+ midMonth.setFullYear(year, month, 15);
3509
+ midMonth.setHours(0, 0, 0, 0);
3510
+ const daysInMonth = getDaysInMonth(midMonth);
3511
+
3512
+ // Set the earlier date, allows to wrap Jan 31 to Feb 28
3513
+ _date.setMonth(month, Math.min(day, daysInMonth));
3514
+ return _date;
3405
3515
  }
3406
3516
 
3517
+ /**
3518
+ * The {@link setDate} function options.
3519
+ */
3520
+
3407
3521
  /**
3408
3522
  * @name setDate
3409
3523
  * @category Day Helpers
@@ -3412,24 +3526,30 @@ function setMonth(dirtyDate, dirtyMonth) {
3412
3526
  * @description
3413
3527
  * Set the day of the month to the given date.
3414
3528
  *
3415
- * @param {Date|Number} date - the date to be changed
3416
- * @param {Number} dayOfMonth - the day of the month of the new date
3417
- * @returns {Date} the new date with the day of the month set
3418
- * @throws {TypeError} 2 arguments required
3529
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows using extensions like [`UTCDate`](https://github.com/date-fns/utc).
3530
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
3531
+ *
3532
+ * @param date - The date to be changed
3533
+ * @param dayOfMonth - The day of the month of the new date
3534
+ * @param options - The options
3535
+ *
3536
+ * @returns The new date with the day of the month set
3419
3537
  *
3420
3538
  * @example
3421
3539
  * // Set the 30th day of the month to 1 September 2014:
3422
3540
  * const result = setDate(new Date(2014, 8, 1), 30)
3423
3541
  * //=> Tue Sep 30 2014 00:00:00
3424
3542
  */
3425
- function setDate(dirtyDate, dirtyDayOfMonth) {
3426
- requiredArgs(2, arguments);
3427
- var date = toDate(dirtyDate);
3428
- var dayOfMonth = toInteger(dirtyDayOfMonth);
3429
- date.setDate(dayOfMonth);
3430
- return date;
3543
+ function setDate(date, dayOfMonth, options) {
3544
+ const _date = toDate(date);
3545
+ _date.setDate(dayOfMonth);
3546
+ return _date;
3431
3547
  }
3432
3548
 
3549
+ /**
3550
+ * The {@link setHours} function options.
3551
+ */
3552
+
3433
3553
  /**
3434
3554
  * @name setHours
3435
3555
  * @category Hour Helpers
@@ -3438,24 +3558,30 @@ function setDate(dirtyDate, dirtyDayOfMonth) {
3438
3558
  * @description
3439
3559
  * Set the hours to the given date.
3440
3560
  *
3441
- * @param {Date|Number} date - the date to be changed
3442
- * @param {Number} hours - the hours of the new date
3443
- * @returns {Date} the new date with the hours set
3444
- * @throws {TypeError} 2 arguments required
3561
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3562
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
3563
+ *
3564
+ * @param date - The date to be changed
3565
+ * @param hours - The hours of the new date
3566
+ * @param options - An object with options
3567
+ *
3568
+ * @returns The new date with the hours set
3445
3569
  *
3446
3570
  * @example
3447
3571
  * // Set 4 hours to 1 September 2014 11:30:00:
3448
3572
  * const result = setHours(new Date(2014, 8, 1, 11, 30), 4)
3449
3573
  * //=> Mon Sep 01 2014 04:30:00
3450
3574
  */
3451
- function setHours(dirtyDate, dirtyHours) {
3452
- requiredArgs(2, arguments);
3453
- var date = toDate(dirtyDate);
3454
- var hours = toInteger(dirtyHours);
3455
- date.setHours(hours);
3456
- return date;
3575
+ function setHours(date, hours, options) {
3576
+ const _date = toDate(date);
3577
+ _date.setHours(hours);
3578
+ return _date;
3457
3579
  }
3458
3580
 
3581
+ /**
3582
+ * The {@link setMinutes} function options.
3583
+ */
3584
+
3459
3585
  /**
3460
3586
  * @name setMinutes
3461
3587
  * @category Minute Helpers
@@ -3464,24 +3590,30 @@ function setHours(dirtyDate, dirtyHours) {
3464
3590
  * @description
3465
3591
  * Set the minutes to the given date.
3466
3592
  *
3467
- * @param {Date|Number} date - the date to be changed
3468
- * @param {Number} minutes - the minutes of the new date
3469
- * @returns {Date} the new date with the minutes set
3470
- * @throws {TypeError} 2 arguments required
3593
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows using extensions like [`UTCDate`](https://github.com/date-fns/utc).
3594
+ * @typeParam ResultDate - The result `Date` type, returned from the context function, or inferred from the arguments.
3595
+ *
3596
+ * @param date - The date to be changed
3597
+ * @param minutes - The minutes of the new date
3598
+ * @param options - An object with options
3599
+ *
3600
+ * @returns The new date with the minutes set
3471
3601
  *
3472
3602
  * @example
3473
3603
  * // Set 45 minutes to 1 September 2014 11:30:40:
3474
3604
  * const result = setMinutes(new Date(2014, 8, 1, 11, 30, 40), 45)
3475
3605
  * //=> Mon Sep 01 2014 11:45:40
3476
3606
  */
3477
- function setMinutes(dirtyDate, dirtyMinutes) {
3478
- requiredArgs(2, arguments);
3479
- var date = toDate(dirtyDate);
3480
- var minutes = toInteger(dirtyMinutes);
3481
- date.setMinutes(minutes);
3482
- return date;
3607
+ function setMinutes(date, minutes, options) {
3608
+ const date_ = toDate(date);
3609
+ date_.setMinutes(minutes);
3610
+ return date_;
3483
3611
  }
3484
3612
 
3613
+ /**
3614
+ * The {@link setYear} function options.
3615
+ */
3616
+
3485
3617
  /**
3486
3618
  * @name setYear
3487
3619
  * @category Year Helpers
@@ -3490,27 +3622,27 @@ function setMinutes(dirtyDate, dirtyMinutes) {
3490
3622
  * @description
3491
3623
  * Set the year to the given date.
3492
3624
  *
3493
- * @param {Date|Number} date - the date to be changed
3494
- * @param {Number} year - the year of the new date
3495
- * @returns {Date} the new date with the year set
3496
- * @throws {TypeError} 2 arguments required
3625
+ * @typeParam DateType - The `Date` type, the function operates on. Gets inferred from passed arguments. Allows to use extensions like [`UTCDate`](https://github.com/date-fns/utc).
3626
+ * @typeParam ResultDate - The result `Date` type, it is the type returned from the context function if it is passed, or inferred from the arguments.
3627
+ *
3628
+ * @param date - The date to be changed
3629
+ * @param year - The year of the new date
3630
+ * @param options - An object with options.
3631
+ *
3632
+ * @returns The new date with the year set
3497
3633
  *
3498
3634
  * @example
3499
3635
  * // Set year 2013 to 1 September 2014:
3500
3636
  * const result = setYear(new Date(2014, 8, 1), 2013)
3501
3637
  * //=> Sun Sep 01 2013 00:00:00
3502
3638
  */
3503
- function setYear(dirtyDate, dirtyYear) {
3504
- requiredArgs(2, arguments);
3505
- var date = toDate(dirtyDate);
3506
- var year = toInteger(dirtyYear);
3639
+ function setYear(date, year, options) {
3640
+ const date_ = toDate(date);
3507
3641
 
3508
3642
  // Check if date is Invalid Date because Date.prototype.setFullYear ignores the value of Invalid Date
3509
- if (isNaN(date.getTime())) {
3510
- return new Date(NaN);
3511
- }
3512
- date.setFullYear(year);
3513
- return date;
3643
+ if (isNaN(+date_)) return constructFrom(date, NaN);
3644
+ date_.setFullYear(year);
3645
+ return date_;
3514
3646
  }
3515
3647
  function CalendarDay(props) {
3516
3648
  const {
@@ -4093,14 +4225,14 @@ function DateInput(props) {
4093
4225
  onChange,
4094
4226
  type,
4095
4227
  value,
4096
- disabled,
4228
+ readOnly,
4097
4229
  ...rest
4098
4230
  } = props;
4099
4231
  const {
4100
4232
  dateFormat
4101
4233
  } = parseOptions(type.options);
4102
4234
  const handleChange = React.useCallback(nextDate => {
4103
- onChange(nextDate);
4235
+ onChange(nextDate || null);
4104
4236
  }, [onChange]);
4105
4237
  const formatInputValue = React.useCallback(date => legacyDateFormat.format(date, dateFormat), [dateFormat]);
4106
4238
  const parseInputValue = React.useCallback(inputValue => legacyDateFormat.parse(inputValue, dateFormat), [dateFormat]);
@@ -4111,7 +4243,7 @@ function DateInput(props) {
4111
4243
  formatInputValue,
4112
4244
  onChange: handleChange,
4113
4245
  parseInputValue,
4114
- readOnly: disabled,
4246
+ readOnly,
4115
4247
  selectTime: false,
4116
4248
  serialize,
4117
4249
  value
@@ -4255,7 +4387,7 @@ function CustomRule(_ref8) {
4255
4387
  return initialValue ? rrule.rrulestr(initialValue) : new rrule.RRule();
4256
4388
  }, [initialValue]);
4257
4389
  const [frequency, setFrequency] = React.useState(initialRule.origOptions.freq || 1);
4258
- const [interval, setInterval] = React.useState(initialRule.origOptions.interval || 1);
4390
+ const [interval, setInterval] = React.useState(initialRule.origOptions.interval && initialRule.origOptions.interval > 0 ? initialRule.origOptions.interval : 1);
4259
4391
  const [count, setCount] = React.useState(initialRule.origOptions.count || null);
4260
4392
  const [until, setUntil] = React.useState(initialRule.origOptions.until || null);
4261
4393
  const [byweekday, setByweekday] = React.useState(initialRule.origOptions.byweekday || null);
@@ -4267,7 +4399,7 @@ function CustomRule(_ref8) {
4267
4399
  if (name === "freq") {
4268
4400
  setFrequency(Number(value));
4269
4401
  } else if (name === "interval") {
4270
- setInterval(Number(value));
4402
+ setInterval(Number(value) > 1 ? Number(value) : 1);
4271
4403
  } else if (name === "count") {
4272
4404
  setCount(Number(value));
4273
4405
  }
@@ -4283,11 +4415,12 @@ function CustomRule(_ref8) {
4283
4415
  } else if (frequency === rrule.RRule.DAILY) {
4284
4416
  fromDate.setDate(fromDate.getDate() + DEFAULT_COUNTS[frequency]);
4285
4417
  }
4418
+ fromDate.setHours(23, 59, 59, 999);
4286
4419
  return fromDate;
4287
4420
  }, [frequency, startDate]);
4288
4421
  const handleUntilChange = React.useCallback(date => {
4289
4422
  if (date) {
4290
- setUntil(new Date(date));
4423
+ setUntil(dateFnsTz.toDate(`${date}T23:59:59`));
4291
4424
  }
4292
4425
  }, []);
4293
4426
  const handleEndChange = React.useCallback(event => {
@@ -4318,6 +4451,7 @@ function CustomRule(_ref8) {
4318
4451
  onClose();
4319
4452
  onChange(sanity.set(newRule.toString(), ["rrule"]));
4320
4453
  }, [byweekday, count, frequency, interval, onChange, onClose, until]);
4454
+ const formatUntilValue = React.useCallback(date => dateFnsTz.format(date, "yyyy-MM-dd"), []);
4321
4455
  return open ? /* @__PURE__ */jsxRuntime.jsx(ui.Dialog, {
4322
4456
  header: "Custom recurrence",
4323
4457
  id: "dialog-example",
@@ -4347,6 +4481,7 @@ function CustomRule(_ref8) {
4347
4481
  children: /* @__PURE__ */jsxRuntime.jsx(ui.TextInput, {
4348
4482
  name: "interval",
4349
4483
  type: "number",
4484
+ min: 1,
4350
4485
  value: interval,
4351
4486
  onChange: handleChange
4352
4487
  })
@@ -4357,16 +4492,16 @@ function CustomRule(_ref8) {
4357
4492
  onChange: handleChange,
4358
4493
  children: [/* @__PURE__ */jsxRuntime.jsx("option", {
4359
4494
  value: rrule.RRule.YEARLY,
4360
- children: "years"
4495
+ children: "year(s)"
4361
4496
  }), /* @__PURE__ */jsxRuntime.jsx("option", {
4362
4497
  value: rrule.RRule.MONTHLY,
4363
- children: "months"
4498
+ children: "month(s)"
4364
4499
  }), /* @__PURE__ */jsxRuntime.jsx("option", {
4365
4500
  value: rrule.RRule.WEEKLY,
4366
- children: "weeks"
4501
+ children: "week(s)"
4367
4502
  }), /* @__PURE__ */jsxRuntime.jsx("option", {
4368
4503
  value: rrule.RRule.DAILY,
4369
- children: "days"
4504
+ children: "day(s)"
4370
4505
  })]
4371
4506
  })
4372
4507
  })]
@@ -4423,8 +4558,8 @@ function CustomRule(_ref8) {
4423
4558
  title: "Date",
4424
4559
  options: dateTimeOptions
4425
4560
  },
4426
- value: until ? new Date(until) : getUntilDate(),
4427
- disabled: !until
4561
+ value: until ? formatUntilValue(new Date(until)) : formatUntilValue(getUntilDate()),
4562
+ readOnly: !until
4428
4563
  })
4429
4564
  })]
4430
4565
  }), /* @__PURE__ */jsxRuntime.jsxs(ui.Flex, {
@@ -4458,7 +4593,7 @@ function CustomRule(_ref8) {
4458
4593
  style: {
4459
4594
  whiteSpace: "nowrap"
4460
4595
  },
4461
- children: "occurrences"
4596
+ children: "occurrence(s)"
4462
4597
  })]
4463
4598
  })]
4464
4599
  })]
@@ -4667,6 +4802,7 @@ function RecurringDates(props) {
4667
4802
  return null;
4668
4803
  }
4669
4804
  const rule = rrule.rrulestr(recurrence);
4805
+ rule.options.until = rule?.options?.until && rrule.datetime(rule?.options?.until?.getFullYear(), rule?.options?.until?.getMonth() + 1, rule?.options?.until?.getDate(), rule?.options?.until?.getHours(), rule?.options?.until?.getMinutes(), rule?.options?.until?.getSeconds());
4670
4806
  return /* @__PURE__ */jsxRuntime.jsx("option", {
4671
4807
  value: recurrence,
4672
4808
  children: lodash.upperFirst(rule.toText())
@@ -4705,6 +4841,9 @@ function RecurringDatesPreview(props) {
4705
4841
  ...options
4706
4842
  };
4707
4843
  const rule = rrule$1 && rrule.rrulestr(rrule$1);
4844
+ if (rule) {
4845
+ rule.options.until = rule?.options?.until && rrule.datetime(rule?.options?.until?.getFullYear(), rule?.options?.until?.getMonth() + 1, rule?.options?.until?.getDate(), rule?.options?.until?.getHours(), rule?.options?.until?.getMinutes(), rule?.options?.until?.getSeconds());
4846
+ }
4708
4847
  const dateFormat = dateTimeOptions?.dateFormat || legacyDateFormat.DEFAULT_DATE_FORMAT;
4709
4848
  const timeFormat = dateTimeOptions?.timeFormat || legacyDateFormat.DEFAULT_TIME_FORMAT;
4710
4849
  const start = startDate ? new Date(startDate) : void 0;