littlewing 0.7.1 → 0.8.0

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.
package/README.md CHANGED
@@ -209,23 +209,21 @@ interface ExecutionContext {
209
209
 
210
210
  The `defaultContext` includes these built-in functions:
211
211
 
212
- **Math:** `ABS`, `CEIL`, `FLOOR`, `ROUND`, `SQRT`, `MIN`, `MAX`, `SIN`, `COS`, `TAN`, `LOG`, `LOG10`, `EXP`
212
+ **Math:** `ABS`, `CEIL`, `FLOOR`, `ROUND`, `SQRT`, `MIN`, `MAX`, `CLAMP`, `SIN`, `COS`, `TAN`, `LOG`, `LOG10`, `EXP`
213
213
 
214
214
  **Timestamps:** `NOW`, `DATE`
215
215
 
216
- **Time converters (to milliseconds):** `FROM_SECONDS`, `FROM_MINUTES`, `FROM_HOURS`, `FROM_DAYS`, `FROM_WEEKS`, `FROM_MONTHS`, `FROM_YEARS`
216
+ **Time converters (to milliseconds):** `FROM_DAYS`, `FROM_WEEKS`, `FROM_MONTHS`, `FROM_YEARS`
217
217
 
218
218
  **Date component extractors:** `GET_YEAR`, `GET_MONTH`, `GET_DAY`, `GET_HOUR`, `GET_MINUTE`, `GET_SECOND`, `GET_WEEKDAY`, `GET_MILLISECOND`, `GET_DAY_OF_YEAR`, `GET_QUARTER`
219
219
 
220
- **Time differences (always positive):** `DIFFERENCE_IN_SECONDS`, `DIFFERENCE_IN_MINUTES`, `DIFFERENCE_IN_HOURS`, `DIFFERENCE_IN_DAYS`, `DIFFERENCE_IN_WEEKS`
220
+ **Time differences (always positive):** `DIFFERENCE_IN_SECONDS`, `DIFFERENCE_IN_MINUTES`, `DIFFERENCE_IN_HOURS`, `DIFFERENCE_IN_DAYS`, `DIFFERENCE_IN_WEEKS`, `DIFFERENCE_IN_MONTHS`, `DIFFERENCE_IN_YEARS`
221
221
 
222
222
  **Start/End of period:** `START_OF_DAY`, `END_OF_DAY`, `START_OF_WEEK`, `START_OF_MONTH`, `END_OF_MONTH`, `START_OF_YEAR`, `END_OF_YEAR`, `START_OF_QUARTER`
223
223
 
224
224
  **Date arithmetic:** `ADD_DAYS`, `ADD_MONTHS`, `ADD_YEARS`
225
225
 
226
- **Date comparisons:** `IS_BEFORE`, `IS_AFTER`, `IS_SAME_DAY`, `IS_WEEKEND`, `IS_LEAP_YEAR`
227
-
228
- **Unix time:** `TO_UNIX_SECONDS`, `FROM_UNIX_SECONDS`
226
+ **Date comparisons:** `IS_SAME_DAY`, `IS_WEEKEND`, `IS_LEAP_YEAR` (use `<`, `>`, `<=`, `>=` operators for before/after comparisons)
229
227
 
230
228
  ## Use Cases
231
229
 
package/dist/index.d.ts CHANGED
@@ -317,35 +317,28 @@ declare class CodeGenerator {
317
317
  */
318
318
  declare function generate(node: ASTNode): string;
319
319
  declare namespace exports_date_utils {
320
- export { TO_UNIX_SECONDS, START_OF_YEAR, START_OF_WEEK, START_OF_QUARTER, START_OF_MONTH, START_OF_DAY, NOW, IS_WEEKEND, IS_SAME_DAY, IS_LEAP_YEAR, IS_BEFORE, IS_AFTER, GET_YEAR, GET_WEEKDAY, GET_SECOND, GET_QUARTER, GET_MONTH, GET_MINUTE, GET_MILLISECOND, GET_HOUR, GET_DAY_OF_YEAR, GET_DAY, FROM_YEARS, FROM_WEEKS, FROM_UNIX_SECONDS, FROM_SECONDS, FROM_MONTHS, FROM_MINUTES, FROM_HOURS, FROM_DAYS, END_OF_YEAR, END_OF_MONTH, END_OF_DAY, DIFFERENCE_IN_WEEKS, DIFFERENCE_IN_SECONDS, DIFFERENCE_IN_MINUTES, DIFFERENCE_IN_HOURS, DIFFERENCE_IN_DAYS, DATE, ADD_YEARS, ADD_MONTHS, ADD_DAYS };
320
+ export { START_OF_YEAR, START_OF_WEEK, START_OF_QUARTER, START_OF_MONTH, START_OF_DAY, NOW, IS_WEEKEND, IS_SAME_DAY, IS_LEAP_YEAR, GET_YEAR, GET_WEEKDAY, GET_SECOND, GET_QUARTER, GET_MONTH, GET_MINUTE, GET_MILLISECOND, GET_HOUR, GET_DAY_OF_YEAR, GET_DAY, FROM_YEARS, FROM_WEEKS, FROM_MONTHS, FROM_DAYS, END_OF_YEAR, END_OF_MONTH, END_OF_DAY, DIFFERENCE_IN_YEARS, DIFFERENCE_IN_WEEKS, DIFFERENCE_IN_SECONDS, DIFFERENCE_IN_MONTHS, DIFFERENCE_IN_MINUTES, DIFFERENCE_IN_HOURS, DIFFERENCE_IN_DAYS, DATE, ADD_YEARS, ADD_MONTHS, ADD_DAYS };
321
321
  }
322
322
  /**
323
323
  * Date utility functions for working with timestamps
324
324
  * All functions work with milliseconds since Unix epoch (numbers only)
325
+ *
326
+ * IMPORTANT: All functions use UTC timezone for consistency and predictability
327
+ * across different server environments. This ensures the same inputs always
328
+ * produce the same outputs regardless of the machine's local timezone.
325
329
  */
326
330
  /**
327
331
  * Get current timestamp (milliseconds since Unix epoch)
328
332
  */
329
333
  declare const NOW: () => number;
330
334
  /**
331
- * Create timestamp from date components
335
+ * Create timestamp from date components (UTC timezone)
332
336
  * Year is required, all other parameters default to minimum values
333
337
  * Month is 1-based (1 = January, 12 = December)
338
+ * All parameters are interpreted in UTC timezone for consistency
334
339
  */
335
340
  declare const DATE: (year: number, month?: number, day?: number, hour?: number, minute?: number, second?: number) => number;
336
341
  /**
337
- * Convert seconds to milliseconds
338
- */
339
- declare const FROM_SECONDS: (s: number) => number;
340
- /**
341
- * Convert minutes to milliseconds
342
- */
343
- declare const FROM_MINUTES: (m: number) => number;
344
- /**
345
- * Convert hours to milliseconds
346
- */
347
- declare const FROM_HOURS: (h: number) => number;
348
- /**
349
342
  * Convert days to milliseconds
350
343
  */
351
344
  declare const FROM_DAYS: (d: number) => number;
@@ -355,150 +348,159 @@ declare const FROM_DAYS: (d: number) => number;
355
348
  declare const FROM_WEEKS: (w: number) => number;
356
349
  /**
357
350
  * Convert months to milliseconds (approximate: 30 days per month)
351
+ * WARNING: This is an approximation. Not all months have 30 days.
352
+ * For accurate month arithmetic, use ADD_MONTHS() instead.
358
353
  */
359
354
  declare const FROM_MONTHS: (months: number) => number;
360
355
  /**
361
356
  * Convert years to milliseconds (approximate: 365 days per year)
357
+ * WARNING: This is an approximation. Leap years have 366 days.
358
+ * For accurate year arithmetic, use ADD_YEARS() instead.
362
359
  */
363
360
  declare const FROM_YEARS: (years: number) => number;
364
361
  /**
365
- * Get the year from a timestamp
362
+ * Get the year from a timestamp (UTC)
366
363
  */
367
364
  declare const GET_YEAR: (timestamp: number) => number;
368
365
  /**
369
- * Get the month from a timestamp (1-based: 1 = January, 12 = December)
366
+ * Get the month from a timestamp (1-based: 1 = January, 12 = December, UTC)
370
367
  */
371
368
  declare const GET_MONTH: (timestamp: number) => number;
372
369
  /**
373
- * Get the day of month from a timestamp (1-31)
370
+ * Get the day of month from a timestamp (1-31, UTC)
374
371
  */
375
372
  declare const GET_DAY: (timestamp: number) => number;
376
373
  /**
377
- * Get the hour from a timestamp (0-23)
374
+ * Get the hour from a timestamp (0-23, UTC)
378
375
  */
379
376
  declare const GET_HOUR: (timestamp: number) => number;
380
377
  /**
381
- * Get the minute from a timestamp (0-59)
378
+ * Get the minute from a timestamp (0-59, UTC)
382
379
  */
383
380
  declare const GET_MINUTE: (timestamp: number) => number;
384
381
  /**
385
- * Get the second from a timestamp (0-59)
382
+ * Get the second from a timestamp (0-59, UTC)
386
383
  */
387
384
  declare const GET_SECOND: (timestamp: number) => number;
388
385
  /**
389
- * Get the millisecond component from a timestamp (0-999)
386
+ * Get the millisecond component from a timestamp (0-999, UTC)
390
387
  */
391
388
  declare const GET_MILLISECOND: (timestamp: number) => number;
392
389
  /**
393
- * Get the day of week from a timestamp (0 = Sunday, 6 = Saturday)
390
+ * Get the day of week from a timestamp (0 = Sunday, 6 = Saturday, UTC)
394
391
  */
395
392
  declare const GET_WEEKDAY: (timestamp: number) => number;
396
393
  /**
397
- * Get the day of year (1-366) from a timestamp
394
+ * Get the day of year (1-366) from a timestamp (UTC)
395
+ * January 1st = 1, December 31st = 365 or 366 (leap year)
398
396
  */
399
397
  declare const GET_DAY_OF_YEAR: (timestamp: number) => number;
400
398
  /**
401
- * Get the quarter (1-4) from a timestamp
399
+ * Get the quarter (1-4) from a timestamp (UTC)
402
400
  */
403
401
  declare const GET_QUARTER: (timestamp: number) => number;
404
402
  /**
405
- * Get the absolute difference between two timestamps in seconds
403
+ * Get the absolute difference between two timestamps in seconds (whole seconds)
406
404
  */
407
405
  declare const DIFFERENCE_IN_SECONDS: (ts1: number, ts2: number) => number;
408
406
  /**
409
- * Get the absolute difference between two timestamps in minutes
407
+ * Get the absolute difference between two timestamps in minutes (whole minutes)
410
408
  */
411
409
  declare const DIFFERENCE_IN_MINUTES: (ts1: number, ts2: number) => number;
412
410
  /**
413
- * Get the absolute difference between two timestamps in hours
411
+ * Get the absolute difference between two timestamps in hours (whole hours)
414
412
  */
415
413
  declare const DIFFERENCE_IN_HOURS: (ts1: number, ts2: number) => number;
416
414
  /**
417
- * Get the absolute difference between two timestamps in days
415
+ * Get the absolute difference between two timestamps in days (whole days)
418
416
  */
419
417
  declare const DIFFERENCE_IN_DAYS: (ts1: number, ts2: number) => number;
420
418
  /**
421
- * Get the absolute difference between two timestamps in weeks
419
+ * Get the absolute difference between two timestamps in weeks (whole weeks)
422
420
  */
423
421
  declare const DIFFERENCE_IN_WEEKS: (ts1: number, ts2: number) => number;
424
422
  /**
425
- * Get the start of day (00:00:00.000) for a given timestamp
423
+ * Get the number of full calendar months between two timestamps (UTC)
424
+ * Counts complete months where the same day-of-month has been reached
425
+ *
426
+ * Examples:
427
+ * Jan 15 → Feb 14 = 0 months (Feb 15 not reached yet)
428
+ * Jan 15 → Feb 15 = 1 month
429
+ * Jan 31 → Feb 28 = 0 months (Feb 31 doesn't exist)
430
+ * Jan 31 → Mar 31 = 2 months
431
+ */
432
+ declare const DIFFERENCE_IN_MONTHS: (ts1: number, ts2: number) => number;
433
+ /**
434
+ * Get the number of full calendar years between two timestamps (UTC)
435
+ * Counts complete years where the same month and day have been reached
436
+ *
437
+ * Examples:
438
+ * Jan 15, 2020 → Jan 14, 2021 = 0 years (Jan 15 not reached)
439
+ * Jan 15, 2020 → Jan 15, 2021 = 1 year
440
+ * Feb 29, 2020 → Feb 28, 2021 = 0 years (Feb 29 doesn't exist)
441
+ * Feb 29, 2020 → Mar 1, 2021 = 1 year
442
+ */
443
+ declare const DIFFERENCE_IN_YEARS: (ts1: number, ts2: number) => number;
444
+ /**
445
+ * Get the start of day (00:00:00.000 UTC) for a given timestamp
426
446
  */
427
447
  declare const START_OF_DAY: (timestamp: number) => number;
428
448
  /**
429
- * Get the end of day (23:59:59.999) for a given timestamp
449
+ * Get the end of day (23:59:59.999 UTC) for a given timestamp
430
450
  */
431
451
  declare const END_OF_DAY: (timestamp: number) => number;
432
452
  /**
433
- * Get the start of week (Sunday at 00:00:00.000) for a given timestamp
453
+ * Get the start of week (Sunday at 00:00:00.000 UTC) for a given timestamp
434
454
  */
435
455
  declare const START_OF_WEEK: (timestamp: number) => number;
436
456
  /**
437
- * Get the start of month (1st day at 00:00:00.000) for a given timestamp
457
+ * Get the start of month (1st day at 00:00:00.000 UTC) for a given timestamp
438
458
  */
439
459
  declare const START_OF_MONTH: (timestamp: number) => number;
440
460
  /**
441
- * Get the end of month (last day at 23:59:59.999) for a given timestamp
461
+ * Get the end of month (last day at 23:59:59.999 UTC) for a given timestamp
442
462
  */
443
463
  declare const END_OF_MONTH: (timestamp: number) => number;
444
464
  /**
445
- * Get the start of year (Jan 1st at 00:00:00.000) for a given timestamp
465
+ * Get the start of year (Jan 1st at 00:00:00.000 UTC) for a given timestamp
446
466
  */
447
467
  declare const START_OF_YEAR: (timestamp: number) => number;
448
468
  /**
449
- * Get the end of year (Dec 31st at 23:59:59.999) for a given timestamp
469
+ * Get the end of year (Dec 31st at 23:59:59.999 UTC) for a given timestamp
450
470
  */
451
471
  declare const END_OF_YEAR: (timestamp: number) => number;
452
472
  /**
453
- * Add days to a timestamp
473
+ * Add days to a timestamp (UTC)
454
474
  */
455
475
  declare const ADD_DAYS: (timestamp: number, days: number) => number;
456
476
  /**
457
- * Add months to a timestamp (handles variable month lengths correctly)
477
+ * Add months to a timestamp (handles variable month lengths correctly, UTC)
458
478
  */
459
479
  declare const ADD_MONTHS: (timestamp: number, months: number) => number;
460
480
  /**
461
- * Add years to a timestamp
481
+ * Add years to a timestamp (UTC)
462
482
  */
463
483
  declare const ADD_YEARS: (timestamp: number, years: number) => number;
464
484
  /**
465
- * Check if ts1 is before ts2
466
- * Returns 1 if true, 0 if false
467
- */
468
- declare const IS_BEFORE: (ts1: number, ts2: number) => number;
469
- /**
470
- * Check if ts1 is after ts2
471
- * Returns 1 if true, 0 if false
472
- */
473
- declare const IS_AFTER: (ts1: number, ts2: number) => number;
474
- /**
475
- * Check if two timestamps are on the same calendar day
485
+ * Check if two timestamps are on the same calendar day (UTC)
476
486
  * Returns 1 if true, 0 if false
477
487
  */
478
488
  declare const IS_SAME_DAY: (ts1: number, ts2: number) => number;
479
489
  /**
480
- * Check if timestamp falls on a weekend (Saturday or Sunday)
490
+ * Check if timestamp falls on a weekend (Saturday or Sunday, UTC)
481
491
  * Returns 1 if true, 0 if false
482
492
  */
483
493
  declare const IS_WEEKEND: (timestamp: number) => number;
484
494
  /**
485
- * Check if timestamp is in a leap year
495
+ * Check if timestamp is in a leap year (UTC)
486
496
  * Returns 1 if true, 0 if false
487
497
  */
488
498
  declare const IS_LEAP_YEAR: (timestamp: number) => number;
489
499
  /**
490
- * Get the start of quarter for a given timestamp
500
+ * Get the start of quarter for a given timestamp (UTC)
491
501
  */
492
502
  declare const START_OF_QUARTER: (timestamp: number) => number;
493
503
  /**
494
- * Convert millisecond timestamp to Unix seconds
495
- */
496
- declare const TO_UNIX_SECONDS: (timestamp: number) => number;
497
- /**
498
- * Convert Unix seconds to millisecond timestamp
499
- */
500
- declare const FROM_UNIX_SECONDS: (seconds: number) => number;
501
- /**
502
504
  * Default execution context with common Math functions and date/time utilities
503
505
  * Users can use this as-is or spread it into their own context
504
506
  *
package/dist/index.js CHANGED
@@ -410,7 +410,6 @@ function generate(node) {
410
410
  // src/date-utils.ts
411
411
  var exports_date_utils = {};
412
412
  __export(exports_date_utils, {
413
- TO_UNIX_SECONDS: () => TO_UNIX_SECONDS,
414
413
  START_OF_YEAR: () => START_OF_YEAR,
415
414
  START_OF_WEEK: () => START_OF_WEEK,
416
415
  START_OF_QUARTER: () => START_OF_QUARTER,
@@ -420,8 +419,6 @@ __export(exports_date_utils, {
420
419
  IS_WEEKEND: () => IS_WEEKEND,
421
420
  IS_SAME_DAY: () => IS_SAME_DAY,
422
421
  IS_LEAP_YEAR: () => IS_LEAP_YEAR,
423
- IS_BEFORE: () => IS_BEFORE,
424
- IS_AFTER: () => IS_AFTER,
425
422
  GET_YEAR: () => GET_YEAR,
426
423
  GET_WEEKDAY: () => GET_WEEKDAY,
427
424
  GET_SECOND: () => GET_SECOND,
@@ -434,17 +431,15 @@ __export(exports_date_utils, {
434
431
  GET_DAY: () => GET_DAY,
435
432
  FROM_YEARS: () => FROM_YEARS,
436
433
  FROM_WEEKS: () => FROM_WEEKS,
437
- FROM_UNIX_SECONDS: () => FROM_UNIX_SECONDS,
438
- FROM_SECONDS: () => FROM_SECONDS,
439
434
  FROM_MONTHS: () => FROM_MONTHS,
440
- FROM_MINUTES: () => FROM_MINUTES,
441
- FROM_HOURS: () => FROM_HOURS,
442
435
  FROM_DAYS: () => FROM_DAYS,
443
436
  END_OF_YEAR: () => END_OF_YEAR,
444
437
  END_OF_MONTH: () => END_OF_MONTH,
445
438
  END_OF_DAY: () => END_OF_DAY,
439
+ DIFFERENCE_IN_YEARS: () => DIFFERENCE_IN_YEARS,
446
440
  DIFFERENCE_IN_WEEKS: () => DIFFERENCE_IN_WEEKS,
447
441
  DIFFERENCE_IN_SECONDS: () => DIFFERENCE_IN_SECONDS,
442
+ DIFFERENCE_IN_MONTHS: () => DIFFERENCE_IN_MONTHS,
448
443
  DIFFERENCE_IN_MINUTES: () => DIFFERENCE_IN_MINUTES,
449
444
  DIFFERENCE_IN_HOURS: () => DIFFERENCE_IN_HOURS,
450
445
  DIFFERENCE_IN_DAYS: () => DIFFERENCE_IN_DAYS,
@@ -454,123 +449,114 @@ __export(exports_date_utils, {
454
449
  ADD_DAYS: () => ADD_DAYS
455
450
  });
456
451
  var NOW = () => Date.now();
457
- var DATE = (year, month = 1, day = 1, hour = 0, minute = 0, second = 0) => new Date(year, month - 1, day, hour, minute, second).getTime();
458
- var FROM_SECONDS = (s) => s * 1000;
459
- var FROM_MINUTES = (m) => m * 60 * 1000;
460
- var FROM_HOURS = (h) => h * 60 * 60 * 1000;
452
+ var DATE = (year, month = 1, day = 1, hour = 0, minute = 0, second = 0) => Date.UTC(year, month - 1, day, hour, minute, second);
461
453
  var FROM_DAYS = (d) => d * 24 * 60 * 60 * 1000;
462
454
  var FROM_WEEKS = (w) => w * 7 * 24 * 60 * 60 * 1000;
463
455
  var FROM_MONTHS = (months) => months * 30 * 24 * 60 * 60 * 1000;
464
456
  var FROM_YEARS = (years) => years * 365 * 24 * 60 * 60 * 1000;
465
- var GET_YEAR = (timestamp) => new Date(timestamp).getFullYear();
466
- var GET_MONTH = (timestamp) => new Date(timestamp).getMonth() + 1;
467
- var GET_DAY = (timestamp) => new Date(timestamp).getDate();
468
- var GET_HOUR = (timestamp) => new Date(timestamp).getHours();
469
- var GET_MINUTE = (timestamp) => new Date(timestamp).getMinutes();
470
- var GET_SECOND = (timestamp) => new Date(timestamp).getSeconds();
471
- var GET_MILLISECOND = (timestamp) => new Date(timestamp).getMilliseconds();
472
- var GET_WEEKDAY = (timestamp) => new Date(timestamp).getDay();
457
+ var GET_YEAR = (timestamp) => new Date(timestamp).getUTCFullYear();
458
+ var GET_MONTH = (timestamp) => new Date(timestamp).getUTCMonth() + 1;
459
+ var GET_DAY = (timestamp) => new Date(timestamp).getUTCDate();
460
+ var GET_HOUR = (timestamp) => new Date(timestamp).getUTCHours();
461
+ var GET_MINUTE = (timestamp) => new Date(timestamp).getUTCMinutes();
462
+ var GET_SECOND = (timestamp) => new Date(timestamp).getUTCSeconds();
463
+ var GET_MILLISECOND = (timestamp) => new Date(timestamp).getUTCMilliseconds();
464
+ var GET_WEEKDAY = (timestamp) => new Date(timestamp).getUTCDay();
473
465
  var GET_DAY_OF_YEAR = (timestamp) => {
474
466
  const date = new Date(timestamp);
475
- const start = new Date(date.getFullYear(), 0, 0);
476
- const diff = date.getTime() - start.getTime();
477
- const oneDay = 1000 * 60 * 60 * 24;
478
- return Math.floor(diff / oneDay);
467
+ const year = date.getUTCFullYear();
468
+ const startOfYear = Date.UTC(year, 0, 1);
469
+ const diff = timestamp - startOfYear;
470
+ const oneDay = 86400000;
471
+ return Math.floor(diff / oneDay) + 1;
479
472
  };
480
473
  var GET_QUARTER = (timestamp) => {
481
- const month = new Date(timestamp).getMonth();
474
+ const month = new Date(timestamp).getUTCMonth();
482
475
  return Math.floor(month / 3) + 1;
483
476
  };
484
- var DIFFERENCE_IN_SECONDS = (ts1, ts2) => Math.abs(ts1 - ts2) / 1000;
485
- var DIFFERENCE_IN_MINUTES = (ts1, ts2) => Math.abs(ts1 - ts2) / (60 * 1000);
486
- var DIFFERENCE_IN_HOURS = (ts1, ts2) => Math.abs(ts1 - ts2) / (60 * 60 * 1000);
487
- var DIFFERENCE_IN_DAYS = (ts1, ts2) => Math.abs(ts1 - ts2) / (24 * 60 * 60 * 1000);
488
- var DIFFERENCE_IN_WEEKS = (ts1, ts2) => Math.abs(ts1 - ts2) / (7 * 24 * 60 * 60 * 1000);
477
+ var DIFFERENCE_IN_SECONDS = (ts1, ts2) => Math.floor(Math.abs(ts1 - ts2) / 1000);
478
+ var DIFFERENCE_IN_MINUTES = (ts1, ts2) => Math.floor(Math.abs(ts1 - ts2) / (60 * 1000));
479
+ var DIFFERENCE_IN_HOURS = (ts1, ts2) => Math.floor(Math.abs(ts1 - ts2) / (60 * 60 * 1000));
480
+ var DIFFERENCE_IN_DAYS = (ts1, ts2) => Math.floor(Math.abs(ts1 - ts2) / (24 * 60 * 60 * 1000));
481
+ var DIFFERENCE_IN_WEEKS = (ts1, ts2) => Math.floor(Math.abs(ts1 - ts2) / (7 * 24 * 60 * 60 * 1000));
482
+ var DIFFERENCE_IN_MONTHS = (ts1, ts2) => {
483
+ const smaller = Math.min(ts1, ts2);
484
+ const larger = Math.max(ts1, ts2);
485
+ const date1 = new Date(smaller);
486
+ const date2 = new Date(larger);
487
+ const yearDiff = date2.getUTCFullYear() - date1.getUTCFullYear();
488
+ const monthDiff = date2.getUTCMonth() - date1.getUTCMonth();
489
+ let months = yearDiff * 12 + monthDiff;
490
+ if (date2.getUTCDate() < date1.getUTCDate()) {
491
+ months--;
492
+ }
493
+ return months;
494
+ };
495
+ var DIFFERENCE_IN_YEARS = (ts1, ts2) => {
496
+ return Math.floor(DIFFERENCE_IN_MONTHS(ts1, ts2) / 12);
497
+ };
489
498
  var START_OF_DAY = (timestamp) => {
490
499
  const date = new Date(timestamp);
491
- date.setHours(0, 0, 0, 0);
492
- return date.getTime();
500
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 0, 0, 0, 0);
493
501
  };
494
502
  var END_OF_DAY = (timestamp) => {
495
503
  const date = new Date(timestamp);
496
- date.setHours(23, 59, 59, 999);
497
- return date.getTime();
504
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), 23, 59, 59, 999);
498
505
  };
499
506
  var START_OF_WEEK = (timestamp) => {
500
507
  const date = new Date(timestamp);
501
- const day = date.getDay();
502
- const diff = date.getDate() - day;
503
- date.setDate(diff);
504
- date.setHours(0, 0, 0, 0);
505
- return date.getTime();
508
+ const dayOfWeek = date.getUTCDay();
509
+ const currentDay = date.getUTCDate();
510
+ const startDay = currentDay - dayOfWeek;
511
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), startDay, 0, 0, 0, 0);
506
512
  };
507
513
  var START_OF_MONTH = (timestamp) => {
508
514
  const date = new Date(timestamp);
509
- date.setDate(1);
510
- date.setHours(0, 0, 0, 0);
511
- return date.getTime();
515
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), 1, 0, 0, 0, 0);
512
516
  };
513
517
  var END_OF_MONTH = (timestamp) => {
514
518
  const date = new Date(timestamp);
515
- date.setMonth(date.getMonth() + 1, 0);
516
- date.setHours(23, 59, 59, 999);
517
- return date.getTime();
519
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + 1, 0, 23, 59, 59, 999);
518
520
  };
519
521
  var START_OF_YEAR = (timestamp) => {
520
522
  const date = new Date(timestamp);
521
- date.setMonth(0, 1);
522
- date.setHours(0, 0, 0, 0);
523
- return date.getTime();
523
+ return Date.UTC(date.getUTCFullYear(), 0, 1, 0, 0, 0, 0);
524
524
  };
525
525
  var END_OF_YEAR = (timestamp) => {
526
526
  const date = new Date(timestamp);
527
- date.setMonth(11, 31);
528
- date.setHours(23, 59, 59, 999);
529
- return date.getTime();
527
+ return Date.UTC(date.getUTCFullYear(), 11, 31, 23, 59, 59, 999);
530
528
  };
531
529
  var ADD_DAYS = (timestamp, days) => {
532
530
  const date = new Date(timestamp);
533
- date.setDate(date.getDate() + days);
534
- return date.getTime();
531
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate() + days, date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
535
532
  };
536
533
  var ADD_MONTHS = (timestamp, months) => {
537
534
  const date = new Date(timestamp);
538
- date.setMonth(date.getMonth() + months);
539
- return date.getTime();
535
+ return Date.UTC(date.getUTCFullYear(), date.getUTCMonth() + months, date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
540
536
  };
541
537
  var ADD_YEARS = (timestamp, years) => {
542
538
  const date = new Date(timestamp);
543
- date.setFullYear(date.getFullYear() + years);
544
- return date.getTime();
545
- };
546
- var IS_BEFORE = (ts1, ts2) => {
547
- return ts1 < ts2 ? 1 : 0;
548
- };
549
- var IS_AFTER = (ts1, ts2) => {
550
- return ts1 > ts2 ? 1 : 0;
539
+ return Date.UTC(date.getUTCFullYear() + years, date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds(), date.getUTCMilliseconds());
551
540
  };
552
541
  var IS_SAME_DAY = (ts1, ts2) => {
553
542
  const date1 = new Date(ts1);
554
543
  const date2 = new Date(ts2);
555
- return date1.getFullYear() === date2.getFullYear() && date1.getMonth() === date2.getMonth() && date1.getDate() === date2.getDate() ? 1 : 0;
544
+ return date1.getUTCFullYear() === date2.getUTCFullYear() && date1.getUTCMonth() === date2.getUTCMonth() && date1.getUTCDate() === date2.getUTCDate() ? 1 : 0;
556
545
  };
557
546
  var IS_WEEKEND = (timestamp) => {
558
- const day = new Date(timestamp).getDay();
547
+ const day = new Date(timestamp).getUTCDay();
559
548
  return day === 0 || day === 6 ? 1 : 0;
560
549
  };
561
550
  var IS_LEAP_YEAR = (timestamp) => {
562
- const year = new Date(timestamp).getFullYear();
551
+ const year = new Date(timestamp).getUTCFullYear();
563
552
  return year % 4 === 0 && year % 100 !== 0 || year % 400 === 0 ? 1 : 0;
564
553
  };
565
554
  var START_OF_QUARTER = (timestamp) => {
566
555
  const date = new Date(timestamp);
567
- const quarter = Math.floor(date.getMonth() / 3);
568
- date.setMonth(quarter * 3, 1);
569
- date.setHours(0, 0, 0, 0);
570
- return date.getTime();
556
+ const month = date.getUTCMonth();
557
+ const quarterStartMonth = Math.floor(month / 3) * 3;
558
+ return Date.UTC(date.getUTCFullYear(), quarterStartMonth, 1, 0, 0, 0, 0);
571
559
  };
572
- var TO_UNIX_SECONDS = (timestamp) => Math.floor(timestamp / 1000);
573
- var FROM_UNIX_SECONDS = (seconds) => seconds * 1000;
574
560
  // src/defaults.ts
575
561
  var defaultContext = {
576
562
  functions: {
@@ -587,6 +573,9 @@ var defaultContext = {
587
573
  LOG: Math.log,
588
574
  LOG10: Math.log10,
589
575
  EXP: Math.exp,
576
+ CLAMP: (value, min, max) => {
577
+ return value < min ? min : value > max ? max : value;
578
+ },
590
579
  ...exports_date_utils
591
580
  }
592
581
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "littlewing",
3
- "version": "0.7.1",
3
+ "version": "0.8.0",
4
4
  "description": "A minimal, high-performance arithmetic expression language with lexer, parser, and executor. Optimized for browsers with zero dependencies and type-safe execution.",
5
5
  "keywords": [
6
6
  "arithmetic",