@happychef/algorithm 1.2.24 → 1.2.25

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.
@@ -3,6 +3,39 @@
3
3
  const { timeblocksAvailable } = require('./processing/timeblocksAvailable');
4
4
  const { parseTime, getMealTypeByTime } = require('./tableHelpers');
5
5
 
6
+ /**
7
+ * Gets the current date/time components in the specified timezone.
8
+ * Uses Intl.DateTimeFormat for reliable cross-browser timezone conversion.
9
+ * @param {Date} date - The date to convert.
10
+ * @param {string} timeZone - The IANA timezone identifier.
11
+ * @returns {Object} Object with year, month, day, hour, minute, second components.
12
+ */
13
+ function getDatePartsInTimeZone(date, timeZone) {
14
+ const formatter = new Intl.DateTimeFormat('en-US', {
15
+ timeZone,
16
+ year: 'numeric',
17
+ month: '2-digit',
18
+ day: '2-digit',
19
+ hour: '2-digit',
20
+ minute: '2-digit',
21
+ second: '2-digit',
22
+ hour12: false,
23
+ });
24
+ const parts = formatter.formatToParts(date);
25
+ const values = {};
26
+ for (const part of parts) {
27
+ values[part.type] = part.value;
28
+ }
29
+ return {
30
+ year: parseInt(values.year, 10),
31
+ month: parseInt(values.month, 10),
32
+ day: parseInt(values.day, 10),
33
+ hour: parseInt(values.hour, 10),
34
+ minute: parseInt(values.minute, 10),
35
+ second: parseInt(values.second, 10),
36
+ };
37
+ }
38
+
6
39
  /**
7
40
  * Parses a time string in "HH:MM" format into a Date object on a specific date.
8
41
  * @param {string} dateStr - The date string in "YYYY-MM-DD" format.
@@ -54,10 +87,13 @@ function getAvailableTimeblocks(data, dateStr, reservations, guests, blockedSlot
54
87
  // Time zone for CEST/CET (Europe/Amsterdam)
55
88
  const timeZone = 'Europe/Amsterdam';
56
89
 
57
- // Current date/time in local timezone (system time)
58
- // Note: We assume the server is running in the correct timezone
90
+ // Get current time in target timezone using reliable cross-browser method
59
91
  const now = new Date();
60
- const currentTimeInTimeZone = now;
92
+ const nowParts = getDatePartsInTimeZone(now, timeZone);
93
+ const currentTimeInTimeZone = new Date(
94
+ nowParts.year, nowParts.month - 1, nowParts.day,
95
+ nowParts.hour, nowParts.minute, nowParts.second
96
+ );
61
97
 
62
98
  // Calculate the maximum allowed date
63
99
  const maxAllowedDate = new Date(currentTimeInTimeZone.getTime());
@@ -75,8 +111,9 @@ function getAvailableTimeblocks(data, dateStr, reservations, guests, blockedSlot
75
111
  }
76
112
 
77
113
  // Check if the target date is today in the specified time zone
114
+ // Compare year, month, day components to determine if it's today
78
115
  const isToday =
79
- currentTimeInTimeZone.toDateString() === targetDateInTimeZone.toDateString();
116
+ nowParts.year === year && nowParts.month === month && nowParts.day === day;
80
117
 
81
118
  // Get available time blocks or shifts
82
119
  const availableTimeblocks = timeblocksAvailable(data, dateStr, reservations, guests, blockedSlots, giftcard, isAdmin, duration);
@@ -12,6 +12,39 @@ function parseTime(timeStr) {
12
12
  return hours * 60 + minutes;
13
13
  }
14
14
 
15
+ /**
16
+ * Gets the current date/time components in the specified timezone.
17
+ * Uses Intl.DateTimeFormat for reliable cross-browser timezone conversion.
18
+ * @param {Date} date - The date to convert.
19
+ * @param {string} timeZone - The IANA timezone identifier.
20
+ * @returns {Object} Object with year, month, day, hour, minute, second components.
21
+ */
22
+ function getDatePartsInTimeZone(date, timeZone) {
23
+ const formatter = new Intl.DateTimeFormat('en-US', {
24
+ timeZone,
25
+ year: 'numeric',
26
+ month: '2-digit',
27
+ day: '2-digit',
28
+ hour: '2-digit',
29
+ minute: '2-digit',
30
+ second: '2-digit',
31
+ hour12: false,
32
+ });
33
+ const parts = formatter.formatToParts(date);
34
+ const values = {};
35
+ for (const part of parts) {
36
+ values[part.type] = part.value;
37
+ }
38
+ return {
39
+ year: parseInt(values.year, 10),
40
+ month: parseInt(values.month, 10),
41
+ day: parseInt(values.day, 10),
42
+ hour: parseInt(values.hour, 10),
43
+ minute: parseInt(values.minute, 10),
44
+ second: parseInt(values.second, 10),
45
+ };
46
+ }
47
+
15
48
  /**
16
49
  * Checks if a date is within the allowed future range defined by dagenInToekomst.
17
50
  * @param {Object} data - The main data object (to access general settings).
@@ -31,20 +64,21 @@ function isDateWithinAllowedRange(data, dateStr) {
31
64
 
32
65
  const timeZone = 'Europe/Amsterdam';
33
66
 
67
+ // Get current time in the target timezone using reliable cross-browser method
34
68
  const now = new Date();
69
+ const nowParts = getDatePartsInTimeZone(now, timeZone);
35
70
  const currentTimeInTimeZone = new Date(
36
- now.toLocaleString('en-US', { timeZone: timeZone })
71
+ nowParts.year, nowParts.month - 1, nowParts.day,
72
+ nowParts.hour, nowParts.minute, nowParts.second
37
73
  );
38
74
 
39
75
  const maxAllowedDate = new Date(currentTimeInTimeZone.getTime());
40
76
  maxAllowedDate.setDate(maxAllowedDate.getDate() + dagenInToekomst);
41
77
  maxAllowedDate.setHours(23, 59, 59, 999);
42
78
 
79
+ // Parse target date - already in local date format, no timezone conversion needed
43
80
  const [year, month, day] = dateStr.split('-').map(Number);
44
- const targetDate = new Date(Date.UTC(year, month - 1, day));
45
- const targetDateInTimeZone = new Date(
46
- targetDate.toLocaleString('en-US', { timeZone: timeZone })
47
- );
81
+ const targetDateInTimeZone = new Date(year, month - 1, day);
48
82
 
49
83
  return targetDateInTimeZone <= maxAllowedDate;
50
84
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@happychef/algorithm",
3
- "version": "1.2.24",
3
+ "version": "1.2.25",
4
4
  "description": "Restaurant and reservation algorithm utilities",
5
5
  "main": "index.js",
6
6
  "scripts": {