/src/server/Extensions/System.cs

https://github.com/mrellipse/toucan · C# · 128 lines · 98 code · 30 blank · 0 comment · 15 complexity · eadc0a376143d0edb5263f6c4e257706 MD5 · raw file

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. using System.IO;
  5. using System.Linq;
  6. using System.Text.RegularExpressions;
  7. using Toucan.Contract;
  8. namespace Toucan.Server
  9. {
  10. public static partial class Extensions
  11. {
  12. private delegate DateTime? ConversionStrategy(string value, CultureInfo culture, TimeZoneInfo sourceTimeZone);
  13. private static ConversionStrategy[] ConversionStrategies = new ConversionStrategy[] { StrategyISO, StrategyUTC, StrategyGMT, StrategyUserCulture };
  14. public static DateTime? FromSourceUtc(this string value, CultureInfo culture, TimeZoneInfo sourceTimeZone)
  15. {
  16. DateTime? result = null;
  17. foreach (var strategy in ConversionStrategies)
  18. {
  19. result = strategy(value, culture, sourceTimeZone);
  20. if (result.HasValue)
  21. break;
  22. }
  23. return result;
  24. }
  25. public static DateTime? ToSourceUtc(this DateTime date, TimeZoneInfo sourceTimeZone)
  26. {
  27. DateTime? dateTime = null;
  28. DateTime sourceDateTime = TimeZoneInfo.ConvertTime(date, TimeZoneInfo.Local, sourceTimeZone);
  29. dateTime = TimeZoneInfo.ConvertTimeToUtc(sourceDateTime, sourceTimeZone);
  30. return dateTime;
  31. }
  32. private static bool ApplySpecifiedOffset(string value)
  33. {
  34. return !value.Contains("+0000") && !value.Contains("Greenwich", StringComparison.CurrentCultureIgnoreCase);
  35. }
  36. private static TimeSpan GetSpecifiedOffset(string value)
  37. {
  38. var match = Regex.Match(value, @"(?:GMT)([\d\+|-]{5})").ToString().Replace("GMT", "");
  39. bool positive = match.StartsWith("+");
  40. int hours = Int32.Parse(match.Substring(1, 2));
  41. int minutes = Int32.Parse(match.Substring(3, 2));
  42. return positive ? new TimeSpan(hours, minutes, 0) : new TimeSpan(hours, minutes, 0).Negate();
  43. }
  44. private static DateTime? StrategyISO(string value, CultureInfo culture, TimeZoneInfo sourceTimeZone)
  45. {
  46. if (value.EndsWith("Z") && value.Contains("T")) // Javascript = new Date().toISOString()
  47. return DateTime.Parse(value, culture, DateTimeStyles.AdjustToUniversal);
  48. return null;
  49. }
  50. private static DateTime? StrategyGMT(string value, CultureInfo culture, TimeZoneInfo sourceTimeZone)
  51. {
  52. if (Regex.IsMatch(value, @"(GMT\+[\d]+\s\([\w\s]+\))+")) // Javascript = new Date().toString()
  53. {
  54. var values = value.Split(" ").ToArray();
  55. if (ApplySpecifiedOffset(value))
  56. {
  57. var date = DateTime.Parse($"{values[0]} {values[1]} {values[2]} {values[3]} {values[4]} GMT", culture, DateTimeStyles.AdjustToUniversal);
  58. TimeSpan adjustment = GetSpecifiedOffset(value);
  59. if (adjustment >= TimeSpan.Zero)
  60. adjustment = adjustment.Negate();
  61. return date.Add(adjustment);
  62. }
  63. else
  64. {
  65. var date = DateTime.Parse($"{values[0]} {values[1]} {values[2]} {values[3]} {values[4]} GMT", culture, DateTimeStyles.AssumeLocal);
  66. date = TimeZoneInfo.ConvertTimeToUtc(date, TimeZoneInfo.Local);
  67. return new DateTime(date.Year, date.Month, date.Day, date.Hour, date.Minute, date.Second, DateTimeKind.Utc);
  68. }
  69. }
  70. return null;
  71. }
  72. private static DateTime? StrategyUserCulture(string value, CultureInfo culture, TimeZoneInfo sourceTimeZone)
  73. {
  74. DateTimeStyles styles = DateTimeStyles.AllowInnerWhite | DateTimeStyles.AllowLeadingWhite | DateTimeStyles.AllowTrailingWhite;
  75. DateTime date;
  76. if (DateTime.TryParse(value, culture.DateTimeFormat, styles, out date))
  77. return new Nullable<DateTime>(date);
  78. if (DateTime.TryParse(value, CultureInfo.InvariantCulture, styles, out date))
  79. return new Nullable<DateTime>(date);
  80. string[] values = value.Split(" ");
  81. if (values.Length == 3 && !value.Contains(",") && value.EndsWith("M"))
  82. {
  83. if (DateTime.TryParse($"{values[0]}, {values[1]} {values[2]}", culture.DateTimeFormat, styles, out date))
  84. return new Nullable<DateTime>(date);
  85. }
  86. return null;
  87. }
  88. private static DateTime? StrategyUTC(string value, CultureInfo culture, TimeZoneInfo sourceTimeZone)
  89. {
  90. if (value.EndsWith("GMT")) // Javascript = new Date().toUTCString()
  91. {
  92. var values = value.Split(" ").ToArray();
  93. return DateTime.Parse($"{values[0]} {values[1]} {values[2]} {values[3]} {values[4]} GMT", culture, DateTimeStyles.AdjustToUniversal);
  94. }
  95. return null;
  96. }
  97. }
  98. }