DatePresentation.cs 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091
  1. using System.Runtime.InteropServices;
  2. using Jint.Native.Date;
  3. namespace Jint.Native;
  4. [Flags]
  5. internal enum DateFlags : byte
  6. {
  7. None = 0,
  8. NaN = 1,
  9. Infinity = 2,
  10. DateTimeMinValue = 4,
  11. DateTimeMaxValue = 8
  12. }
  13. [StructLayout(LayoutKind.Auto)]
  14. internal readonly record struct DatePresentation(long Value, DateFlags Flags)
  15. {
  16. public static readonly DatePresentation NaN = new(0, DateFlags.NaN);
  17. public static readonly DatePresentation MinValue = new(JsDate.Min, DateFlags.DateTimeMinValue);
  18. public static readonly DatePresentation MaxValue = new(JsDate.Max, DateFlags.DateTimeMaxValue);
  19. public bool DateTimeRangeValid => IsFinite && Value <= JsDate.Max && Value >= JsDate.Min;
  20. public bool IsNaN => (Flags & DateFlags.NaN) != DateFlags.None;
  21. public bool IsInfinity => (Flags & DateFlags.Infinity) != DateFlags.None;
  22. public bool IsFinite => (Flags & (DateFlags.NaN | DateFlags.Infinity)) == DateFlags.None;
  23. public DateTime ToDateTime()
  24. {
  25. return DateConstructor.Epoch.AddMilliseconds(Value);
  26. }
  27. public static implicit operator DatePresentation(long value)
  28. {
  29. return new DatePresentation(value, DateFlags.None);
  30. }
  31. public static implicit operator DatePresentation(double value)
  32. {
  33. if (double.IsInfinity(value))
  34. {
  35. return new DatePresentation(0, DateFlags.Infinity);
  36. }
  37. if (double.IsNaN(value))
  38. {
  39. return new DatePresentation(0, DateFlags.NaN);
  40. }
  41. return new DatePresentation((long) value, DateFlags.None);
  42. }
  43. public static DatePresentation operator +(DatePresentation a, DatePresentation b)
  44. {
  45. if (a.IsNaN || b.IsNaN)
  46. {
  47. return NaN;
  48. }
  49. return new DatePresentation(a.Value + b.Value, DateFlags.None);
  50. }
  51. public static DatePresentation operator -(DatePresentation a, DatePresentation b) => a + -b;
  52. public static DatePresentation operator +(DatePresentation a) => a;
  53. public static DatePresentation operator -(DatePresentation a) => a with { Value = -a.Value };
  54. internal DatePresentation TimeClip()
  55. {
  56. if ((Flags & (DateFlags.NaN | DateFlags.Infinity)) != DateFlags.None)
  57. {
  58. return NaN;
  59. }
  60. if (Value is < -8640000000000000 or > 8640000000000000)
  61. {
  62. return NaN;
  63. }
  64. return this;
  65. }
  66. internal JsNumber ToJsValue()
  67. {
  68. if (IsNaN || Value is < -8640000000000000 or > 8640000000000000)
  69. {
  70. return JsNumber.DoubleNaN;
  71. }
  72. return JsNumber.Create(Value);
  73. }
  74. }