File size: 2,355 Bytes
cf86710
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { TZDate } from "@date-fns/tz";
import type { Matcher } from "../types/index.js";
import { toTimeZone } from "./toTimeZone.js";
import {
  isDateAfterType,
  isDateBeforeType,
  isDateInterval,
  isDateRange,
} from "./typeguards.js";

function toZoneNoon(date: Date, timeZone: string, noonSafe?: boolean) {
  if (!noonSafe) return toTimeZone(date, timeZone);
  const zoned = toTimeZone(date, timeZone);
  const noonZoned = new TZDate(
    zoned.getFullYear(),
    zoned.getMonth(),
    zoned.getDate(),
    12,
    0,
    0,
    timeZone,
  );
  return new Date(noonZoned.getTime());
}

function convertMatcher(
  matcher: Matcher,
  timeZone: string,
  noonSafe?: boolean,
): Matcher {
  if (typeof matcher === "boolean" || typeof matcher === "function") {
    return matcher;
  }

  if (matcher instanceof Date) {
    return toZoneNoon(matcher, timeZone, noonSafe);
  }

  if (Array.isArray(matcher)) {
    return matcher.map((value) =>
      value instanceof Date ? toZoneNoon(value, timeZone, noonSafe) : value,
    );
  }

  if (isDateRange(matcher)) {
    return {
      ...matcher,
      from: matcher.from ? toTimeZone(matcher.from, timeZone) : matcher.from,
      to: matcher.to ? toTimeZone(matcher.to, timeZone) : matcher.to,
    };
  }

  if (isDateInterval(matcher)) {
    return {
      before: toZoneNoon(matcher.before, timeZone, noonSafe),
      after: toZoneNoon(matcher.after, timeZone, noonSafe),
    };
  }

  if (isDateAfterType(matcher)) {
    return {
      after: toZoneNoon(matcher.after, timeZone, noonSafe),
    };
  }

  if (isDateBeforeType(matcher)) {
    return {
      before: toZoneNoon(matcher.before, timeZone, noonSafe),
    };
  }

  return matcher;
}

/**
 * Convert any {@link Matcher} or array of matchers to the specified time zone.
 *
 * @param matchers - The matcher or matchers to convert.
 * @param timeZone - The target IANA time zone.
 * @returns The converted matcher(s).
 * @group Utilities
 */
export function convertMatchersToTimeZone(
  matchers: Matcher | Matcher[] | undefined,
  timeZone: string,
  noonSafe?: boolean,
): Matcher | Matcher[] | undefined {
  if (!matchers) {
    return matchers;
  }

  if (Array.isArray(matchers)) {
    return matchers.map((matcher) =>
      convertMatcher(matcher, timeZone, noonSafe),
    );
  }

  return convertMatcher(matchers, timeZone, noonSafe);
}