dce-reactkit 4.2.6 → 4.2.7

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.
@@ -7,7 +7,7 @@
7
7
  * @param opts.month Month (1-12)
8
8
  * @param opts.day Day of the month (1-31)
9
9
  * @param opts.hour Hour (0-23)
10
- * @param opts.minute Minute (0-59))
10
+ * @param opts.minute Minute (0-59)
11
11
  * @returns Timestamp in milliseconds since epoch
12
12
  */
13
13
  declare const getTimestampFromTimeInfoInET: (opts: {
package/dist/index.d.ts CHANGED
@@ -1604,7 +1604,7 @@ declare const cloneDeep: <T>(obj: T) => T;
1604
1604
  * @param opts.month Month (1-12)
1605
1605
  * @param opts.day Day of the month (1-31)
1606
1606
  * @param opts.hour Hour (0-23)
1607
- * @param opts.minute Minute (0-59))
1607
+ * @param opts.minute Minute (0-59)
1608
1608
  * @returns Timestamp in milliseconds since epoch
1609
1609
  */
1610
1610
  declare const getTimestampFromTimeInfoInET: (opts: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "dce-reactkit",
3
- "version": "4.2.6",
3
+ "version": "4.2.7",
4
4
  "description": "Shared components for Harvard DCE apps",
5
5
  "main": "dist/cjs/index.js",
6
6
  "module": "dist/esm/index.js",
@@ -6,6 +6,80 @@ import ReactKitErrorCode from '../types/ReactKitErrorCode';
6
6
  import getTimeInfoInET from './getTimeInfoInET';
7
7
  import padZerosLeft from './padZerosLeft';
8
8
 
9
+ /*----------------------------------------*/
10
+ /* --------------- Helpers -------------- */
11
+ /*----------------------------------------*/
12
+
13
+ /**
14
+ * Check if a timestamp is valid
15
+ * @author Gabe Abrams
16
+ * @author Gardenia Liu
17
+ * @param opts object containing all arguments
18
+ * @param opts.timestamp Timestamp in milliseconds since epoch
19
+ * @param opts.expectedYear Expected year
20
+ * @param opts.expectedMonth Expected month
21
+ * @param opts.expectedDay Expected day
22
+ * @param opts.expectedHour Expected hour
23
+ * @param opts.expectedMinute Expected minute
24
+ * @returns 1 if the timestamp needs to be increased, -1 if it needs to be decreased, 0 if it is valid
25
+ */
26
+ const checkTimestamp = (
27
+ opts: {
28
+ timestamp: number,
29
+ expectedYear: number,
30
+ expectedMonth: number,
31
+ expectedDay: number,
32
+ expectedHour: number,
33
+ expectedMinute: number,
34
+ },
35
+ ): number => {
36
+ const {
37
+ timestamp,
38
+ expectedYear,
39
+ expectedMonth,
40
+ expectedDay,
41
+ expectedHour,
42
+ expectedMinute,
43
+ } = opts;
44
+
45
+ const timeInfoInET = getTimeInfoInET(timestamp);
46
+ if (timeInfoInET.year < expectedYear) {
47
+ return 1;
48
+ }
49
+ if (timeInfoInET.year > expectedYear) {
50
+ return -1;
51
+ }
52
+ if (timeInfoInET.month < expectedMonth) {
53
+ return 1;
54
+ }
55
+ if (timeInfoInET.month > expectedMonth) {
56
+ return -1;
57
+ }
58
+ if (timeInfoInET.day < expectedDay) {
59
+ return 1;
60
+ }
61
+ if (timeInfoInET.day > expectedDay) {
62
+ return -1;
63
+ }
64
+ if (timeInfoInET.hour < expectedHour) {
65
+ return 1;
66
+ }
67
+ if (timeInfoInET.hour > expectedHour) {
68
+ return -1;
69
+ }
70
+ if (timeInfoInET.minute < expectedMinute) {
71
+ return 1;
72
+ }
73
+ if (timeInfoInET.minute > expectedMinute) {
74
+ return -1;
75
+ }
76
+ return 0;
77
+ };
78
+
79
+ /*----------------------------------------*/
80
+ /* ---------------- Main ---------------- */
81
+ /*----------------------------------------*/
82
+
9
83
  /**
10
84
  * Get a timestamp (ms since epoch) from time info (year, month, day, hour, minute, etc.) in Eastern Time (ET)
11
85
  * @author Gardenia Liu
@@ -15,7 +89,7 @@ import padZerosLeft from './padZerosLeft';
15
89
  * @param opts.month Month (1-12)
16
90
  * @param opts.day Day of the month (1-31)
17
91
  * @param opts.hour Hour (0-23)
18
- * @param opts.minute Minute (0-59))
92
+ * @param opts.minute Minute (0-59)
19
93
  * @returns Timestamp in milliseconds since epoch
20
94
  */
21
95
  const getTimestampFromTimeInfoInET = (
@@ -50,25 +124,55 @@ const getTimestampFromTimeInfoInET = (
50
124
 
51
125
  // Build ET ISO string and convert to UTC timestamp
52
126
  const etISOString = `${year}-${mm}-${dd}T${hh}:${min}:00${etOffset}`;
53
- const timestamp = (new Date(etISOString)).getTime();
127
+ let timestamp = (new Date(etISOString)).getTime();
54
128
 
55
- // Verify that the timestamp is correct
56
- const timeInfoInET = getTimeInfoInET(timestamp);
57
- if (
58
- timeInfoInET.year !== year
59
- || timeInfoInET.month !== month
60
- || timeInfoInET.day !== day
61
- || timeInfoInET.hour !== hour
62
- || timeInfoInET.minute !== minute
63
- ) {
64
- throw new ErrorWithCode(
65
- `Timestamp mismatch: expected ${year}-${mm}-${dd} ${hh}:${min}, got ${timeInfoInET.year}-${padZerosLeft(timeInfoInET.month, 2)}-${padZerosLeft(timeInfoInET.day, 2)} ${padZerosLeft(timeInfoInET.hour, 2)}:${padZerosLeft(timeInfoInET.minute, 2)}`,
66
- ReactKitErrorCode.ETTimestampInvalid,
67
- );
129
+ // Heat seek to get the right timestamp
130
+ const maxOffset = 24 * 60; // 24 hours in minutes
131
+ let currentOffset = 0; // minutes
132
+ const offsetIncrement = 15; // minutes
133
+ const offsetDirection = checkTimestamp({
134
+ timestamp,
135
+ expectedYear: year,
136
+ expectedMonth: month,
137
+ expectedDay: day,
138
+ expectedHour: hour,
139
+ expectedMinute: minute,
140
+ });
141
+ if (offsetDirection === 0) {
142
+ // Valid! Return the timestamp
143
+ return timestamp;
144
+ }
145
+
146
+ // Heat seek
147
+ while (Math.abs(currentOffset) < maxOffset) {
148
+ // Update offset
149
+ currentOffset += (offsetDirection * offsetIncrement);
150
+
151
+ // Update timestamp
152
+ const offsetMs = currentOffset * 60 * 1000;
153
+ timestamp += offsetMs;
154
+
155
+ // Check timestamp again
156
+ const newDirection = checkTimestamp({
157
+ timestamp,
158
+ expectedYear: year,
159
+ expectedMonth: month,
160
+ expectedDay: day,
161
+ expectedHour: hour,
162
+ expectedMinute: minute,
163
+ });
164
+ if (newDirection === 0) {
165
+ // Valid! Return the timestamp
166
+ return timestamp;
167
+ }
168
+
169
+ // Invalid. Keep looping.
68
170
  }
69
171
 
70
- // Valid! Return the timestamp
71
- return timestamp;
172
+ throw new ErrorWithCode(
173
+ `Timestamp mismatch: expected ${year}-${mm}-${dd} ${hh}:${min}, seeked to offset ${currentOffset} minutes but could not find a valid timestamp.`,
174
+ ReactKitErrorCode.ETTimestampInvalid,
175
+ );
72
176
  };
73
177
 
74
178
  export default getTimestampFromTimeInfoInET;