|
5 | 5 | use BitCode\FI\Core\Util\Common; |
6 | 6 | use BitCode\FI\Core\Util\HttpHelper; |
7 | 7 | use BitCode\FI\Log\LogHandler; |
| 8 | +use DateTime; |
| 9 | +use DateTimeImmutable; |
| 10 | +use DateTimeZone; |
| 11 | +use Throwable; |
8 | 12 |
|
9 | 13 | /** |
10 | 14 | * Provide functionality for Record insert,upsert |
@@ -38,6 +42,7 @@ public function generateReqDataFromFieldMap($data, $fieldMap) |
38 | 42 | : $data[$triggerValue] |
39 | 43 | ); |
40 | 44 | } |
| 45 | + error_log('Salesforce Final Data: ' . print_r($dataFinal, true)); |
41 | 46 |
|
42 | 47 | return $dataFinal; |
43 | 48 | } |
@@ -279,83 +284,146 @@ public function execute($integrationDetails, $fieldValues, $fieldMap, $actions) |
279 | 284 | return true; |
280 | 285 | } |
281 | 286 |
|
282 | | - public static function convertToSalesforceFormat($inputDate) |
| 287 | + public static function convertToSalesforceFormat($input) |
283 | 288 | { |
284 | | - // First, strip any leading/trailing spaces |
285 | | - $inputDate = trim($inputDate); |
286 | | - |
287 | | - // Handle 2-digit year date formats (like 25/11/13 or 11/25/13) |
288 | | - if (preg_match("/^\d{2}\/\d{2}\/\d{2}$/", $inputDate)) { |
289 | | - // Convert DD/MM/YY or MM/DD/YY to YYYY-MM-DD |
290 | | - $parts = explode('/', $inputDate); |
291 | | - if (\strlen($parts[2]) == 2) { |
292 | | - // Handling 2-digit year (assuming the year is in the 2000s) |
293 | | - $year = '20' . $parts[2]; |
294 | | - $month = $parts[1]; |
295 | | - $day = $parts[0]; |
296 | | - $formattedDate = "{$year}-{$month}-{$day}"; |
297 | | - } |
298 | | - // Validate and return the formatted date |
299 | | - if (strtotime($formattedDate)) { |
300 | | - return $formattedDate; // Return in YYYY-MM-DD format |
301 | | - } |
| 289 | + if (!$input || !\is_string($input)) { |
| 290 | + return $input; |
| 291 | + } |
302 | 292 |
|
303 | | - return $inputDate; |
| 293 | + $input = trim($input); |
| 294 | + |
| 295 | + // ------------------------------------------------------------ |
| 296 | + // 1) Handle UNIX timestamps (10 or 13 digits) |
| 297 | + // ------------------------------------------------------------ |
| 298 | + if (preg_match('/^\d{10}$/', $input)) { |
| 299 | + return gmdate('Y-m-d\TH:i:s\Z', (int) $input); |
| 300 | + } |
| 301 | + if (preg_match('/^\d{13}$/', $input)) { |
| 302 | + return gmdate('Y-m-d\TH:i:s\Z', (int) ($input / 1000)); |
304 | 303 | } |
305 | 304 |
|
306 | | - // Handle formats like DD/MM/YYYY or MM/DD/YYYY |
307 | | - if (preg_match("/^\d{2}\/\d{2}\/\d{4}$/", $inputDate)) { |
308 | | - // Convert DD/MM/YYYY or MM/DD/YYYY to YYYY-MM-DD |
309 | | - $parts = explode('/', $inputDate); |
310 | | - $year = $parts[2]; |
311 | | - $month = $parts[1]; |
312 | | - $day = $parts[0]; |
313 | | - $formattedDate = "{$year}-{$month}-{$day}"; |
314 | | - // Validate and return the formatted date |
315 | | - if (strtotime($formattedDate)) { |
316 | | - return $formattedDate; // Return in YYYY-MM-DD format |
| 305 | + // ------------------------------------------------------------ |
| 306 | + // 2) Natural-language dates ("today", "tomorrow", "next Monday", etc.) |
| 307 | + // ------------------------------------------------------------ |
| 308 | + if (preg_match('/^[a-zA-Z ]+$/', $input) || str_contains($input, 'ago')) { |
| 309 | + $ts = strtotime($input); |
| 310 | + if ($ts) { |
| 311 | + return gmdate('Y-m-d', $ts); |
317 | 312 | } |
| 313 | + } |
318 | 314 |
|
319 | | - return $inputDate; |
| 315 | + // ------------------------------------------------------------ |
| 316 | + // 3) Clean ordinals: 1st, 2nd, 3rd, 21st, 31st... |
| 317 | + // ------------------------------------------------------------ |
| 318 | + $clean = preg_replace('/\b(\d+)(st|nd|rd|th)\b/i', '$1', $input); |
| 319 | + |
| 320 | + // ------------------------------------------------------------ |
| 321 | + // 4) Japanese/Chinese/Korean locale replacements |
| 322 | + // ------------------------------------------------------------ |
| 323 | + $clean = str_replace( |
| 324 | + ['年', '月', '日', '년', '월', '일'], |
| 325 | + ['-', '-', '', '-', '-', ''], |
| 326 | + $clean |
| 327 | + ); |
| 328 | + |
| 329 | + // ------------------------------------------------------------ |
| 330 | + // 5) Week-based formats (2025-W05 or 2025-W05-6) |
| 331 | + // ------------------------------------------------------------ |
| 332 | + if (preg_match('/^(\d{4})-?W(\d{2})(?:-?(\d))?$/i', $clean, $m)) { |
| 333 | + $year = $m[1]; |
| 334 | + $week = $m[2]; |
| 335 | + $day = $m[3] ?? 1; |
| 336 | + |
| 337 | + try { |
| 338 | + $dt = new DateTime("{$year}-W{$week}-{$day}", new DateTimeZone('UTC')); |
| 339 | + |
| 340 | + return $dt->format('Y-m-d'); |
| 341 | + } catch (Throwable $e) { |
| 342 | + } |
320 | 343 | } |
321 | 344 |
|
322 | | - // Handle formats like YYYY-MM-DD |
323 | | - if (preg_match("/^\d{4}-\d{2}-\d{2}$/", $inputDate)) { |
324 | | - // It's already in the correct format (YYYY-MM-DD) |
325 | | - return $inputDate; |
| 345 | + // ------------------------------------------------------------ |
| 346 | + // 6) Quarter formats (Q1 2025, 2025 Q1, 1st Quarter 2025) |
| 347 | + // ------------------------------------------------------------ |
| 348 | + if (preg_match('/(Q[1-4]|[1-4]st Quarter)\s*[, ]*\s*(\d{4})/i', $clean, $m)) { |
| 349 | + $q = preg_replace('/\D/', '', $m[1]); // Extract 1–4 |
| 350 | + $year = $m[2]; |
| 351 | + $month = (($q - 1) * 3) + 1; |
| 352 | + |
| 353 | + return "{$year}-" . str_pad($month, 2, '0', STR_PAD_LEFT) . '-01'; |
326 | 354 | } |
327 | 355 |
|
328 | | - // Handle formats like YYYY/MM/DD |
329 | | - if (preg_match("/^\d{4}\/\d{2}\/\d{2}$/", $inputDate)) { |
330 | | - // Convert YYYY/MM/DD to YYYY-MM-DD |
331 | | - $formattedDate = str_replace('/', '-', $inputDate); |
332 | | - // Validate and return the formatted date |
333 | | - if (strtotime($formattedDate)) { |
334 | | - return $formattedDate; // Return in YYYY-MM-DD format |
| 356 | + // ------------------------------------------------------------ |
| 357 | + // 7) Compact numeric formats (01022025, 20250201, 250201, 010225) |
| 358 | + // ------------------------------------------------------------ |
| 359 | + if (preg_match('/^\d{8}$/', $clean)) { |
| 360 | + // YYYYMMDD or DDMMYYYY or MMDDYYYY → try multiple interpretations |
| 361 | + $candidates = [ |
| 362 | + substr($clean, 0, 4) . '-' . substr($clean, 4, 2) . '-' . substr($clean, 6, 2), // YMD |
| 363 | + substr($clean, 4, 4) . '-' . substr($clean, 2, 2) . '-' . substr($clean, 0, 2), // DMY |
| 364 | + ]; |
| 365 | + foreach ($candidates as $c) { |
| 366 | + if (strtotime($c)) { |
| 367 | + return $c; |
| 368 | + } |
335 | 369 | } |
| 370 | + } |
336 | 371 |
|
337 | | - return $inputDate; |
| 372 | + if (preg_match('/^\d{6}$/', $clean)) { |
| 373 | + // DDMMYY / YYMMDD / MMDDYY |
| 374 | + $yy = substr($clean, -2); |
| 375 | + $year = $yy > 70 ? "19{$yy}" : "20{$yy}"; |
| 376 | + |
| 377 | + $dm = substr($clean, 0, 2) . '-' . substr($clean, 2, 2) . '-' . $year; |
| 378 | + $md = substr($clean, 2, 2) . '-' . substr($clean, 0, 2) . '-' . $year; |
| 379 | + |
| 380 | + foreach ([$dm, $md] as $c) { |
| 381 | + $ts = strtotime($c); |
| 382 | + if ($ts) { |
| 383 | + return gmdate('Y-m-d', $ts); |
| 384 | + } |
| 385 | + } |
338 | 386 | } |
339 | 387 |
|
340 | | - // Handle date formats with time: YYYY-MM-DD HH:MM:SS |
341 | | - if (preg_match("/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}(:\d{2}(\.\d{1,3})?)?$/", $inputDate)) { |
342 | | - // It's a datetime with or without milliseconds |
343 | | - $date = strtotime($inputDate); |
344 | | - if ($date === false) { |
345 | | - return $inputDate; |
| 388 | + // ------------------------------------------------------------ |
| 389 | + // 8) Try direct DateTime parsing for most formats |
| 390 | + // ------------------------------------------------------------ |
| 391 | + $tryParse = function ($value) { |
| 392 | + try { |
| 393 | + return new DateTimeImmutable($value); |
| 394 | + } catch (Throwable $e) { |
| 395 | + return; |
| 396 | + } |
| 397 | + }; |
| 398 | + |
| 399 | + $dt = $tryParse($clean); |
| 400 | + |
| 401 | + if ($dt instanceof DateTimeImmutable) { |
| 402 | + // Detect if datetime or pure date |
| 403 | + if (preg_match('/\d{1,2}:\d/', $clean)) { |
| 404 | + return $dt->setTimezone(new DateTimeZone('UTC')) |
| 405 | + ->format('Y-m-d\TH:i:s\Z'); |
346 | 406 | } |
347 | 407 |
|
348 | | - // Convert to Salesforce ISO 8601 datetime with UTC (Z) |
349 | | - return gmdate("Y-m-d\TH:i:s\Z", $date); // Convert to UTC and add Z |
| 408 | + return $dt->format('Y-m-d'); |
350 | 409 | } |
351 | 410 |
|
352 | | - // Handle datetime formats with ISO 8601 style (e.g., 2025-09-20T10:30:00Z or with milliseconds) |
353 | | - if (preg_match("/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(Z|(\.\d{1,3})?)?$/", $inputDate)) { |
354 | | - // It's already in ISO 8601 format, return as is |
355 | | - return strtoupper($inputDate); // Normalize to uppercase 'Z' if needed |
| 411 | + // ------------------------------------------------------------ |
| 412 | + // 9) Last fallback using strtotime() |
| 413 | + // ------------------------------------------------------------ |
| 414 | + $ts = strtotime($clean); |
| 415 | + if ($ts) { |
| 416 | + // Detect datetime or date-only |
| 417 | + if (preg_match('/\d{1,2}:\d/', $clean)) { |
| 418 | + return gmdate('Y-m-d\TH:i:s\Z', $ts); |
| 419 | + } |
| 420 | + |
| 421 | + return gmdate('Y-m-d', $ts); |
356 | 422 | } |
357 | 423 |
|
358 | | - // If input contains no recognizable date/time format, return an error |
359 | | - return $inputDate; |
| 424 | + // ------------------------------------------------------------ |
| 425 | + // 10) No match → return original |
| 426 | + // ------------------------------------------------------------ |
| 427 | + return $input; |
360 | 428 | } |
361 | 429 | } |
0 commit comments