DateTimeUnitFactory.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.Linq;
  5. namespace ScottPlot.Ticks.DateTimeTickUnits
  6. {
  7. public class DateTimeUnitFactory
  8. {
  9. public IDateTimeUnit Create(DateTimeUnit kind, CultureInfo culture, int maxTickCount, int? manualSpacing)
  10. {
  11. switch (kind)
  12. {
  13. case DateTimeUnit.ThousandYear:
  14. return new DateTimeTickThousandYear(culture, maxTickCount, manualSpacing);
  15. case DateTimeUnit.HundredYear:
  16. return new DateTimeTickHundredYear(culture, maxTickCount, manualSpacing);
  17. case DateTimeUnit.TenYear:
  18. return new DateTimeTickTenYear(culture, maxTickCount, manualSpacing);
  19. case DateTimeUnit.Year:
  20. return new DateTimeTickYear(culture, maxTickCount, manualSpacing);
  21. case DateTimeUnit.Month:
  22. return new DateTimeTickMonth(culture, maxTickCount, manualSpacing);
  23. case DateTimeUnit.Day:
  24. return new DateTimeTickDay(culture, maxTickCount, manualSpacing);
  25. case DateTimeUnit.Hour:
  26. return new DateTimeTickHour(culture, maxTickCount, manualSpacing);
  27. case DateTimeUnit.Minute:
  28. return new DateTimeTickMinute(culture, maxTickCount, manualSpacing);
  29. case DateTimeUnit.Second:
  30. return new DateTimeTickSecond(culture, maxTickCount, manualSpacing);
  31. case DateTimeUnit.Decisecond:
  32. return new DateTimeTickDecisecond(culture, maxTickCount, manualSpacing);
  33. case DateTimeUnit.Centisecond:
  34. return new DateTimeTickCentisecond(culture, maxTickCount, manualSpacing);
  35. case DateTimeUnit.Millisecond:
  36. return new DateTimeTickMillisecond(culture, maxTickCount, manualSpacing);
  37. default:
  38. throw new NotImplementedException("unrecognized TickUnit");
  39. }
  40. }
  41. public IDateTimeUnit CreateBestUnit(DateTime from, DateTime to, CultureInfo culture, int maxTickCount)
  42. {
  43. double daysApart = to.ToOADate() - from.ToOADate();
  44. int halfDensity = maxTickCount / 2;
  45. // tick unit borders in days
  46. var tickUnitBorders = new List<(DateTimeUnit kind, double border)?>
  47. {
  48. (DateTimeUnit.ThousandYear, 365 * 1_000 * halfDensity),
  49. (DateTimeUnit.HundredYear, 365 * 100 * halfDensity),
  50. (DateTimeUnit.TenYear, 365 * 10 * halfDensity),
  51. (DateTimeUnit.Year, 365 * halfDensity),
  52. (DateTimeUnit.Month, 30 * halfDensity),
  53. (DateTimeUnit.Day, 1 * halfDensity),
  54. (DateTimeUnit.Hour, 1.0 / 24 * halfDensity),
  55. (DateTimeUnit.Minute, 1.0 / 24 / 60 * halfDensity),
  56. (DateTimeUnit.Second, 1.0 / 24 / 3600 * halfDensity),
  57. (DateTimeUnit.Decisecond, 1.0 / 24 / 3600 / 10 * halfDensity),
  58. (DateTimeUnit.Centisecond, 1.0 / 24 / 3600 / 100 * halfDensity),
  59. (DateTimeUnit.Millisecond, 1.0 / 24 / 3600 / 1000 * halfDensity),
  60. };
  61. var bestTickUnitKind = tickUnitBorders.FirstOrDefault(tr => daysApart > tr.Value.border);
  62. bestTickUnitKind = bestTickUnitKind ?? tickUnitBorders.Last(); // last tickUnit if not found best
  63. return Create(bestTickUnitKind.Value.kind, culture, maxTickCount, null);
  64. }
  65. public IDateTimeUnit CreateUnit(DateTime from, DateTime to, CultureInfo culture, int maxTickCount, DateTimeUnit? manualUnits, int? manualSpacing)
  66. {
  67. if (manualUnits == null)
  68. {
  69. return CreateBestUnit(from, to, culture, maxTickCount);
  70. }
  71. else
  72. {
  73. return Create(manualUnits.Value, culture, maxTickCount, manualSpacing);
  74. }
  75. }
  76. }
  77. }