(baseTime: Dayjs, timePart: string, originalContext: string)
| 209 | * @returns The resolved Date object. |
| 210 | */ |
| 211 | const processSemanticKeyword = (baseTime: Dayjs, timePart: string, originalContext: string): Date => { |
| 212 | if (!timePart) { |
| 213 | return baseTime.toDate(); |
| 214 | } |
| 215 | |
| 216 | const isPM = REGEX_IS_PM.test(originalContext); |
| 217 | const isAM = REGEX_IS_AM.test(originalContext); |
| 218 | |
| 219 | // Normalize formats like "3pm" to "3 pm" to separate digits from text |
| 220 | const fixTimePart = timePart.replace(REGEX_STICKY_AMPM, '$1 $2m'); |
| 221 | |
| 222 | // Attempt 1: Parse as a duration (e.g., "8点" -> 8 hours from start of day) |
| 223 | const extraDuration = parseDuration(fixTimePart); |
| 224 | let addedMillis = extraDuration.asMilliseconds(); |
| 225 | |
| 226 | // Attempt 2: Handle cases where duration regex fails (e.g., "3 pm" doesn't match standard units) |
| 227 | const stickyMatch = REGEX_STICKY_AMPM.exec(timePart); |
| 228 | if (addedMillis === 0 && stickyMatch) { |
| 229 | addedMillis = Number(stickyMatch[1]) * 60 * 60 * 1000; |
| 230 | } |
| 231 | |
| 232 | if (addedMillis > 0) { |
| 233 | const hours = dayjs.duration(addedMillis).asHours(); |
| 234 | // Adjust for 12-hour clock context |
| 235 | if (isPM && hours < 12) { |
| 236 | addedMillis += 12 * 60 * 60 * 1000; |
| 237 | } else if (isAM && hours === 12) { |
| 238 | addedMillis -= 12 * 60 * 60 * 1000; |
| 239 | } |
| 240 | return baseTime.add(addedMillis, 'ms').toDate(); |
| 241 | } |
| 242 | |
| 243 | // Attempt 3: Parse as a standard time string using Day.js formats |
| 244 | const composedDateStr = `${baseTime.format('YYYY-MM-DD')} ${fixTimePart}`; |
| 245 | const tried = dayjs(composedDateStr, ['YYYY-MM-DD HH:mm:ss', 'YYYY-MM-DD HH:mm', 'YYYY-MM-DD H:m', 'YYYY-MM-DD h:m a', 'YYYY-MM-DD h a']); |
| 246 | |
| 247 | if (tried.isValid()) { |
| 248 | let result = tried; |
| 249 | // Manual adjustment if the parser missed 12-hour context (e.g., "下午" stripped earlier) |
| 250 | if (isPM && result.hour() < 12) { |
| 251 | result = result.add(12, 'hours'); |
| 252 | } |
| 253 | return result.toDate(); |
| 254 | } |
| 255 | |
| 256 | return baseTime.toDate(); |
| 257 | }; |
| 258 | |
| 259 | /** |
| 260 | * Parses a relative or semantic date string into a JavaScript Date object. |
no test coverage detected