From fe3fcda35632a119f7f92a23620d2fc56284defa Mon Sep 17 00:00:00 2001 From: Diego Heras Date: Sat, 14 Mar 2020 17:05:10 +0100 Subject: [PATCH] style: improve date utils code style (#7632) --- .editorconfig | 34 +-- src/DateTimeRoutines/DateTimeRoutines.cs | 289 +++++++++--------- .../Indexers/CardigannIndexer.cs | 8 +- src/Jackett.Common/Utils/DateTimeUtil.cs | 130 ++++---- 4 files changed, 221 insertions(+), 240 deletions(-) diff --git a/.editorconfig b/.editorconfig index 8c2b0544a..6e71a7d21 100644 --- a/.editorconfig +++ b/.editorconfig @@ -123,7 +123,7 @@ dotnet_style_prefer_compound_assignment=true:suggestion ############################### # Style Definitions dotnet_naming_style.pascal_case_style.capitalization=pascal_case -# Use PascalCase for constant fields +# Use PascalCase for constant fields dotnet_naming_rule.constant_fields_should_be_pascal_case.severity=warning dotnet_naming_rule.constant_fields_should_be_pascal_case.symbols=constant_fields dotnet_naming_rule.constant_fields_should_be_pascal_case.style=pascal_case_style @@ -161,11 +161,11 @@ dotnet_naming_rule.asyncmethods_should_be_ends_with_async.style = ends_with_asyn dotnet_naming_symbols.interface.applicable_kinds = interface dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.interface.required_modifiers = +dotnet_naming_symbols.interface.required_modifiers = dotnet_naming_symbols.private_or_internal_field.applicable_kinds = field dotnet_naming_symbols.private_or_internal_field.applicable_accessibilities = internal, private, private_protected -dotnet_naming_symbols.private_or_internal_field.required_modifiers = +dotnet_naming_symbols.private_or_internal_field.required_modifiers = dotnet_naming_symbols.private_or_internal_static_field.applicable_kinds = field dotnet_naming_symbols.private_or_internal_static_field.applicable_accessibilities = internal, private, private_protected @@ -173,11 +173,11 @@ dotnet_naming_symbols.private_or_internal_static_field.required_modifiers = stat dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.types.required_modifiers = +dotnet_naming_symbols.types.required_modifiers = dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal, private_protected -dotnet_naming_symbols.non_field_members.required_modifiers = +dotnet_naming_symbols.non_field_members.required_modifiers = dotnet_naming_symbols.asyncmethods.applicable_kinds = delegate, method, local_function dotnet_naming_symbols.asyncmethods.applicable_accessibilities = * @@ -185,29 +185,29 @@ dotnet_naming_symbols.asyncmethods.required_modifiers = async # Naming styles -dotnet_naming_style.pascal_case.required_prefix = -dotnet_naming_style.pascal_case.required_suffix = -dotnet_naming_style.pascal_case.word_separator = +dotnet_naming_style.pascal_case.required_prefix = +dotnet_naming_style.pascal_case.required_suffix = +dotnet_naming_style.pascal_case.word_separator = dotnet_naming_style.pascal_case.capitalization = pascal_case dotnet_naming_style.begins_with_i.required_prefix = I -dotnet_naming_style.begins_with_i.required_suffix = -dotnet_naming_style.begins_with_i.word_separator = +dotnet_naming_style.begins_with_i.required_suffix = +dotnet_naming_style.begins_with_i.word_separator = dotnet_naming_style.begins_with_i.capitalization = pascal_case -dotnet_naming_style.private_or_internal_static_with_prefix.required_prefix = s_ -dotnet_naming_style.private_or_internal_static_with_prefix.required_suffix = -dotnet_naming_style.private_or_internal_static_with_prefix.word_separator = +dotnet_naming_style.private_or_internal_static_with_prefix.required_prefix = _ +dotnet_naming_style.private_or_internal_static_with_prefix.required_suffix = +dotnet_naming_style.private_or_internal_static_with_prefix.word_separator = dotnet_naming_style.private_or_internal_static_with_prefix.capitalization = pascal_case dotnet_naming_style.private_prefix.required_prefix = _ -dotnet_naming_style.private_prefix.required_suffix = -dotnet_naming_style.private_prefix.word_separator = +dotnet_naming_style.private_prefix.required_suffix = +dotnet_naming_style.private_prefix.word_separator = dotnet_naming_style.private_prefix.capitalization = camel_case -dotnet_naming_style.ends_with_async.required_prefix = +dotnet_naming_style.ends_with_async.required_prefix = dotnet_naming_style.ends_with_async.required_suffix = Async -dotnet_naming_style.ends_with_async.word_separator = +dotnet_naming_style.ends_with_async.word_separator = dotnet_naming_style.ends_with_async.capitalization = pascal_case ############################### diff --git a/src/DateTimeRoutines/DateTimeRoutines.cs b/src/DateTimeRoutines/DateTimeRoutines.cs index 978e75961..3dd323caf 100644 --- a/src/DateTimeRoutines/DateTimeRoutines.cs +++ b/src/DateTimeRoutines/DateTimeRoutines.cs @@ -9,6 +9,10 @@ using System; using System.Text.RegularExpressions; +// ReSharper disable NotAccessedField.Global +// ReSharper disable MemberCanBePrivate.Global +// ReSharper disable UnusedMember.Global + namespace DateTimeRoutines { /// @@ -21,11 +25,11 @@ namespace DateTimeRoutines /// /// Amount of seconds elapsed between 1970-01-01 00:00:00 and the date-time. /// - /// date-time + /// date-time /// seconds - public static uint GetSecondsSinceUnixEpoch(this DateTime date_time) + public static uint GetSecondsSinceUnixEpoch(this DateTime dateTime) { - var t = date_time - new DateTime(1970, 1, 1); + var t = dateTime - new DateTime(1970, 1, 1); var ss = (int)t.TotalSeconds; if (ss < 0) return 0; @@ -44,19 +48,19 @@ namespace DateTimeRoutines /// /// Index of first char of a date substring found in the string /// - public readonly int IndexOfDate = -1; + public readonly int IndexOfDate; /// /// Length a date substring found in the string /// - public readonly int LengthOfDate = -1; + public readonly int LengthOfDate; /// /// Index of first char of a time substring found in the string /// - public readonly int IndexOfTime = -1; + public readonly int IndexOfTime; /// /// Length of a time substring found in the string /// - public readonly int LengthOfTime = -1; + public readonly int LengthOfTime; /// /// DateTime found in the string /// @@ -82,45 +86,45 @@ namespace DateTimeRoutines /// public DateTime UtcDateTime; - internal ParsedDateTime(int index_of_date, int length_of_date, int index_of_time, int length_of_time, DateTime date_time) + internal ParsedDateTime(int indexOfDate, int lengthOfDate, int indexOfTime, int lengthOfTime, DateTime dateTime) { - IndexOfDate = index_of_date; - LengthOfDate = length_of_date; - IndexOfTime = index_of_time; - LengthOfTime = length_of_time; - DateTime = date_time; - IsDateFound = index_of_date > -1; - IsTimeFound = index_of_time > -1; + IndexOfDate = indexOfDate; + LengthOfDate = lengthOfDate; + IndexOfTime = indexOfTime; + LengthOfTime = lengthOfTime; + DateTime = dateTime; + IsDateFound = indexOfDate > -1; + IsTimeFound = indexOfTime > -1; UtcOffset = new TimeSpan(25, 0, 0); IsUtcOffsetFound = false; UtcDateTime = new DateTime(1, 1, 1); } - internal ParsedDateTime(int index_of_date, int length_of_date, int index_of_time, int length_of_time, DateTime date_time, TimeSpan utc_offset) + internal ParsedDateTime(int indexOfDate, int lengthOfDate, int indexOfTime, int lengthOfTime, DateTime dateTime, TimeSpan utcOffset) { - IndexOfDate = index_of_date; - LengthOfDate = length_of_date; - IndexOfTime = index_of_time; - LengthOfTime = length_of_time; - DateTime = date_time; - IsDateFound = index_of_date > -1; - IsTimeFound = index_of_time > -1; - UtcOffset = utc_offset; - IsUtcOffsetFound = Math.Abs(utc_offset.TotalHours) < 12; + IndexOfDate = indexOfDate; + LengthOfDate = lengthOfDate; + IndexOfTime = indexOfTime; + LengthOfTime = lengthOfTime; + DateTime = dateTime; + IsDateFound = indexOfDate > -1; + IsTimeFound = indexOfTime > -1; + UtcOffset = utcOffset; + IsUtcOffsetFound = Math.Abs(utcOffset.TotalHours) < 12; if (!IsUtcOffsetFound) UtcDateTime = new DateTime(1, 1, 1); else { - if (index_of_date < 0)//to avoid negative date exception when date is undefined + if (indexOfDate < 0)//to avoid negative date exception when date is undefined { - var ts = date_time.TimeOfDay + utc_offset; + var ts = dateTime.TimeOfDay + utcOffset; if (ts < new TimeSpan(0)) UtcDateTime = new DateTime(1, 1, 2) + ts; else UtcDateTime = new DateTime(1, 1, 1) + ts; } else - UtcDateTime = date_time + utc_offset; + UtcDateTime = dateTime + utcOffset; } } } @@ -129,7 +133,7 @@ namespace DateTimeRoutines /// Date that is accepted in the following cases: /// - no date was parsed by TryParseDateOrTime(); /// - no year was found by TryParseDate(); - /// It is ignored if DefaultDateIsNow = true was set after DefaultDate + /// It is ignored if DefaultDateIsNow = true was set after DefaultDate /// public static DateTime DefaultDate { @@ -138,13 +142,7 @@ namespace DateTimeRoutines _DefaultDate = value; DefaultDateIsNow = false; } - get - { - if (DefaultDateIsNow) - return DateTime.Now; - else - return _DefaultDate; - } + get => DefaultDateIsNow ? DateTime.Now : _DefaultDate; } private static DateTime _DefaultDate = DateTime.Now; @@ -157,16 +155,17 @@ namespace DateTimeRoutines /// /// Defines default date-time format. /// + [Flags] public enum DateTimeFormat { /// /// month number goes before day number /// - USA_DATE, + UsaDate, /// /// day number goes before month number /// - UK_DATE, + UkDate, ///// ///// time is specifed through AM or PM ///// @@ -178,79 +177,79 @@ namespace DateTimeRoutines #region parsing derived methods for DateTime output /// - /// Tries to find date and time within the passed string and return it as DateTime structure. + /// Tries to find date and time within the passed string and return it as DateTime structure. /// /// string that contains date and/or time - /// format to be used preferably in ambivalent instances - /// parsed date-time output + /// format to be used preferably in ambivalent instances + /// parsed date-time output /// true if both date and time were found, else false - public static bool TryParseDateTime(this string str, DateTimeFormat default_format, out DateTime date_time) + public static bool TryParseDateTime(this string str, DateTimeFormat defaultFormat, out DateTime dateTime) { - if (!TryParseDateTime(str, default_format, out ParsedDateTime parsed_date_time)) + if (!TryParseDateTime(str, defaultFormat, out ParsedDateTime parsedDateTime)) { - date_time = new DateTime(1, 1, 1); + dateTime = new DateTime(1, 1, 1); return false; } - date_time = parsed_date_time.DateTime; + dateTime = parsedDateTime.DateTime; return true; } /// - /// Tries to find date and/or time within the passed string and return it as DateTime structure. + /// Tries to find date and/or time within the passed string and return it as DateTime structure. /// If only date was found, time in the returned DateTime is always 0:0:0. /// If only time was found, date in the returned DateTime is DefaultDate. /// /// string that contains date and(or) time - /// format to be used preferably in ambivalent instances - /// parsed date-time output + /// format to be used preferably in ambivalent instances + /// parsed date-time output /// true if date and/or time was found, else false - public static bool TryParseDateOrTime(this string str, DateTimeFormat default_format, out DateTime date_time) + public static bool TryParseDateOrTime(this string str, DateTimeFormat defaultFormat, out DateTime dateTime) { - if (!TryParseDateOrTime(str, default_format, out ParsedDateTime parsed_date_time)) + if (!TryParseDateOrTime(str, defaultFormat, out ParsedDateTime parsedDateTime)) { - date_time = new DateTime(1, 1, 1); + dateTime = new DateTime(1, 1, 1); return false; } - date_time = parsed_date_time.DateTime; + dateTime = parsedDateTime.DateTime; return true; } /// - /// Tries to find time within the passed string and return it as DateTime structure. + /// Tries to find time within the passed string and return it as DateTime structure. /// It recognizes only time while ignoring date, so date in the returned DateTime is always 1/1/1. /// /// string that contains time - /// format to be used preferably in ambivalent instances + /// format to be used preferably in ambivalent instances /// parsed time output /// true if time was found, else false - public static bool TryParseTime(this string str, DateTimeFormat default_format, out DateTime time) + public static bool TryParseTime(this string str, DateTimeFormat defaultFormat, out DateTime time) { - if (!TryParseTime(str, default_format, out var parsed_time, null)) + if (!TryParseTime(str, defaultFormat, out var parsedTime, null)) { time = new DateTime(1, 1, 1); return false; } - time = parsed_time.DateTime; + time = parsedTime.DateTime; return true; } /// - /// Tries to find date within the passed string and return it as DateTime structure. + /// Tries to find date within the passed string and return it as DateTime structure. /// It recognizes only date while ignoring time, so time in the returned DateTime is always 0:0:0. - /// If year of the date was not found then it accepts the current year. + /// If year of the date was not found then it accepts the current year. /// /// string that contains date - /// format to be used preferably in ambivalent instances + /// format to be used preferably in ambivalent instances /// parsed date output /// true if date was found, else false - public static bool TryParseDate(this string str, DateTimeFormat default_format, out DateTime date) + public static bool TryParseDate(this string str, DateTimeFormat defaultFormat, out DateTime date) { - if (!TryParseDate(str, default_format, out ParsedDateTime parsed_date)) + if (!TryParseDate(str, defaultFormat, out ParsedDateTime parsedDate)) { date = new DateTime(1, 1, 1); return false; } - date = parsed_date.DateTime; + date = parsedDate.DateTime; return true; } @@ -259,69 +258,69 @@ namespace DateTimeRoutines #region parsing derived methods for ParsedDateTime output /// - /// Tries to find date and time within the passed string and return it as ParsedDateTime object. + /// Tries to find date and time within the passed string and return it as ParsedDateTime object. /// /// string that contains date-time - /// format to be used preferably in ambivalent instances - /// parsed date-time output + /// format to be used preferably in ambivalent instances + /// parsed date-time output /// true if both date and time were found, else false - public static bool TryParseDateTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_date_time) + public static bool TryParseDateTime(this string str, DateTimeFormat defaultFormat, out ParsedDateTime parsedDateTime) { - if (DateTimeRoutines.TryParseDateOrTime(str, default_format, out parsed_date_time) - && parsed_date_time.IsDateFound - && parsed_date_time.IsTimeFound + if (TryParseDateOrTime(str, defaultFormat, out parsedDateTime) + && parsedDateTime.IsDateFound + && parsedDateTime.IsTimeFound ) return true; - parsed_date_time = null; + parsedDateTime = null; return false; } /// - /// Tries to find time within the passed string and return it as ParsedDateTime object. + /// Tries to find time within the passed string and return it as ParsedDateTime object. /// It recognizes only time while ignoring date, so date in the returned ParsedDateTime is always 1/1/1 /// /// string that contains date-time - /// format to be used preferably in ambivalent instances - /// parsed date-time output + /// format to be used preferably in ambivalent instances + /// parsed date-time output /// true if time was found, else false - public static bool TryParseTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_time) - => TryParseTime(str, default_format, out parsed_time, null); + public static bool TryParseTime(this string str, DateTimeFormat defaultFormat, out ParsedDateTime parsedTime) + => TryParseTime(str, defaultFormat, out parsedTime, null); /// - /// Tries to find date and/or time within the passed string and return it as ParsedDateTime object. + /// Tries to find date and/or time within the passed string and return it as ParsedDateTime object. /// If only date was found, time in the returned ParsedDateTime is always 0:0:0. /// If only time was found, date in the returned ParsedDateTime is DefaultDate. /// /// string that contains date-time - /// format to be used preferably in ambivalent instances - /// parsed date-time output + /// format to be used preferably in ambivalent instances + /// parsed date-time output /// true if date or time was found, else false - public static bool TryParseDateOrTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_date_time) + public static bool TryParseDateOrTime(this string str, DateTimeFormat defaultFormat, out ParsedDateTime parsedDateTime) { - parsed_date_time = null; + parsedDateTime = null; - ParsedDateTime parsed_time; - if (!TryParseDate(str, default_format, out - ParsedDateTime parsed_date)) + ParsedDateTime parsedTime; + if (!TryParseDate(str, defaultFormat, out + ParsedDateTime parsedDate)) { - if (!TryParseTime(str, default_format, out parsed_time, null)) + if (!TryParseTime(str, defaultFormat, out parsedTime, null)) return false; - var date_time = new DateTime(DefaultDate.Year, DefaultDate.Month, DefaultDate.Day, parsed_time.DateTime.Hour, parsed_time.DateTime.Minute, parsed_time.DateTime.Second); - parsed_date_time = new ParsedDateTime(-1, -1, parsed_time.IndexOfTime, parsed_time.LengthOfTime, date_time, parsed_time.UtcOffset); + var dateTime = new DateTime(DefaultDate.Year, DefaultDate.Month, DefaultDate.Day, parsedTime.DateTime.Hour, parsedTime.DateTime.Minute, parsedTime.DateTime.Second); + parsedDateTime = new ParsedDateTime(-1, -1, parsedTime.IndexOfTime, parsedTime.LengthOfTime, dateTime, parsedTime.UtcOffset); } else { - if (!TryParseTime(str, default_format, out parsed_time, parsed_date)) + if (!TryParseTime(str, defaultFormat, out parsedTime, parsedDate)) { - var date_time = new DateTime(parsed_date.DateTime.Year, parsed_date.DateTime.Month, parsed_date.DateTime.Day, 0, 0, 0); - parsed_date_time = new ParsedDateTime(parsed_date.IndexOfDate, parsed_date.LengthOfDate, -1, -1, date_time); + var dateTime = new DateTime(parsedDate.DateTime.Year, parsedDate.DateTime.Month, parsedDate.DateTime.Day, 0, 0, 0); + parsedDateTime = new ParsedDateTime(parsedDate.IndexOfDate, parsedDate.LengthOfDate, -1, -1, dateTime); } else { - var date_time = new DateTime(parsed_date.DateTime.Year, parsed_date.DateTime.Month, parsed_date.DateTime.Day, parsed_time.DateTime.Hour, parsed_time.DateTime.Minute, parsed_time.DateTime.Second); - parsed_date_time = new ParsedDateTime(parsed_date.IndexOfDate, parsed_date.LengthOfDate, parsed_time.IndexOfTime, parsed_time.LengthOfTime, date_time, parsed_time.UtcOffset); + var dateTime = new DateTime(parsedDate.DateTime.Year, parsedDate.DateTime.Month, parsedDate.DateTime.Day, parsedTime.DateTime.Hour, parsedTime.DateTime.Minute, parsedTime.DateTime.Second); + parsedDateTime = new ParsedDateTime(parsedDate.IndexOfDate, parsedDate.LengthOfDate, parsedTime.IndexOfTime, parsedTime.LengthOfTime, dateTime, parsedTime.UtcOffset); } } @@ -337,42 +336,39 @@ namespace DateTimeRoutines /// It recognizes only time while ignoring date, so date in the returned ParsedDateTime is always 1/1/1 /// /// string that contains date - /// format to be used preferably in ambivalent instances - /// parsed date-time output - /// ParsedDateTime object if the date was found within this string, else NULL + /// format to be used preferably in ambivalent instances + /// parsed date-time output + /// ParsedDateTime object if the date was found within this string, else NULL /// true if time was found, else false - public static bool TryParseTime(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_time, ParsedDateTime parsed_date) + public static bool TryParseTime(this string str, DateTimeFormat defaultFormat, out ParsedDateTime parsedTime, ParsedDateTime parsedDate) { - parsed_time = null; + parsedTime = null; - string time_zone_r; - if (default_format == DateTimeFormat.USA_DATE) - time_zone_r = @"(?:\s*(?'time_zone'UTC|GMT|CST|EST))?"; - else - time_zone_r = @"(?:\s*(?'time_zone'UTC|GMT))?"; + var timeZoneR = defaultFormat == DateTimeFormat.UsaDate ? + @"(?:\s*(?'time_zone'UTC|GMT|CST|EST))?" : @"(?:\s*(?'time_zone'UTC|GMT))?"; Match m; - if (parsed_date != null && parsed_date.IndexOfDate > -1) + if (parsedDate != null && parsedDate.IndexOfDate > -1) {//look around the found date - //look for hh:mm:ss - m = Regex.Match(str.Substring(parsed_date.IndexOfDate + parsed_date.LengthOfDate), @"(?<=^\s*,?\s+|^\s*at\s*|^\s*[T\-]\s*)(?'hour'\d{2})\s*:\s*(?'minute'\d{2})\s*:\s*(?'second'\d{2})\s+(?'offset_sign'[\+\-])(?'offset_hh'\d{2}):?(?'offset_mm'\d{2})(?=$|[^\d\w])", RegexOptions.Compiled); + //look for hh:mm:ss + m = Regex.Match(str.Substring(parsedDate.IndexOfDate + parsedDate.LengthOfDate), @"(?<=^\s*,?\s+|^\s*at\s*|^\s*[T\-]\s*)(?'hour'\d{2})\s*:\s*(?'minute'\d{2})\s*:\s*(?'second'\d{2})\s+(?'offset_sign'[\+\-])(?'offset_hh'\d{2}):?(?'offset_mm'\d{2})(?=$|[^\d\w])", RegexOptions.Compiled); if (!m.Success) - //look for [h]h:mm[:ss] [PM/AM] [UTC/GMT] - m = Regex.Match(str.Substring(parsed_date.IndexOfDate + parsed_date.LengthOfDate), @"(?<=^\s*,?\s+|^\s*at\s*|^\s*[T\-]\s*)(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + time_zone_r + @"(?=$|[^\d\w])", RegexOptions.Compiled); + //look for [h]h:mm[:ss] [PM/AM] [UTC/GMT] + m = Regex.Match(str.Substring(parsedDate.IndexOfDate + parsedDate.LengthOfDate), @"(?<=^\s*,?\s+|^\s*at\s*|^\s*[T\-]\s*)(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + timeZoneR + @"(?=$|[^\d\w])", RegexOptions.Compiled); if (!m.Success) //look for [h]h:mm:ss [PM/AM] [UTC/GMT] - m = Regex.Match(str.Substring(0, parsed_date.IndexOfDate), @"(?<=^|[^\d])(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + time_zone_r + @"(?=$|[\s,]+)", RegexOptions.Compiled); + m = Regex.Match(str.Substring(0, parsedDate.IndexOfDate), @"(?<=^|[^\d])(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + timeZoneR + @"(?=$|[\s,]+)", RegexOptions.Compiled); if (!m.Success) //look for [h]h:mm:ss [PM/AM] [UTC/GMT] within - m = Regex.Match(str.Substring(parsed_date.IndexOfDate, parsed_date.LengthOfDate), @"(?<=^|[^\d])(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + time_zone_r + @"(?=$|[\s,]+)", RegexOptions.Compiled); + m = Regex.Match(str.Substring(parsedDate.IndexOfDate, parsedDate.LengthOfDate), @"(?<=^|[^\d])(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + timeZoneR + @"(?=$|[\s,]+)", RegexOptions.Compiled); } else//look anywhere within string { - //look for hh:mm:ss + //look for hh:mm:ss m = Regex.Match(str, @"(?<=^|\s+|\s*T\s*)(?'hour'\d{2})\s*:\s*(?'minute'\d{2})\s*:\s*(?'second'\d{2})\s+(?'offset_sign'[\+\-])(?'offset_hh'\d{2}):?(?'offset_mm'\d{2})?(?=$|[^\d\w])", RegexOptions.Compiled); if (!m.Success) //look for [h]h:mm[:ss] [PM/AM] [UTC/GMT] - m = Regex.Match(str, @"(?<=^|\s+|\s*T\s*)(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + time_zone_r + @"(?=$|[^\d\w])", RegexOptions.Compiled); + m = Regex.Match(str, @"(?<=^|\s+|\s*T\s*)(?'hour'\d{1,2})\s*:\s*(?'minute'\d{2})\s*(?::\s*(?'second'\d{2}))?(?:\s*(?'ampm'AM|am|PM|pm))?" + timeZoneR + @"(?=$|[^\d\w])", RegexOptions.Compiled); } if (!m.Success) @@ -396,49 +392,49 @@ namespace DateTimeRoutines return false; } - if (string.Compare(m.Groups["ampm"].Value, "PM", true) == 0 && hour < 12) + if ("PM".Equals(m.Groups["ampm"].Value, StringComparison.OrdinalIgnoreCase) && hour < 12) hour += 12; - else if (string.Compare(m.Groups["ampm"].Value, "AM", true) == 0 && hour == 12) + else if ("AM".Equals(m.Groups["ampm"].Value, StringComparison.OrdinalIgnoreCase) && hour == 12) hour -= 12; - var date_time = new DateTime(1, 1, 1, hour, minute, second); + var dateTime = new DateTime(1, 1, 1, hour, minute, second); if (m.Groups["offset_hh"].Success) { - var offset_hh = int.Parse(m.Groups["offset_hh"].Value); - var offset_mm = 0; + var offsetHh = int.Parse(m.Groups["offset_hh"].Value); + var offsetMm = 0; if (m.Groups["offset_mm"].Success) - offset_mm = int.Parse(m.Groups["offset_mm"].Value); - var utc_offset = new TimeSpan(offset_hh, offset_mm, 0); + offsetMm = int.Parse(m.Groups["offset_mm"].Value); + var utcOffset = new TimeSpan(offsetHh, offsetMm, 0); if (m.Groups["offset_sign"].Value == "-") - utc_offset = -utc_offset; - parsed_time = new ParsedDateTime(-1, -1, m.Index, m.Length, date_time, utc_offset); + utcOffset = -utcOffset; + parsedTime = new ParsedDateTime(-1, -1, m.Index, m.Length, dateTime, utcOffset); return true; } if (m.Groups["time_zone"].Success) { - TimeSpan utc_offset; + TimeSpan utcOffset; switch (m.Groups["time_zone"].Value) { case "UTC": case "GMT": - utc_offset = new TimeSpan(0, 0, 0); + utcOffset = new TimeSpan(0, 0, 0); break; case "CST": - utc_offset = new TimeSpan(-6, 0, 0); + utcOffset = new TimeSpan(-6, 0, 0); break; case "EST": - utc_offset = new TimeSpan(-5, 0, 0); + utcOffset = new TimeSpan(-5, 0, 0); break; default: throw new Exception("Time zone: " + m.Groups["time_zone"].Value + " is not defined."); } - parsed_time = new ParsedDateTime(-1, -1, m.Index, m.Length, date_time, utc_offset); + parsedTime = new ParsedDateTime(-1, -1, m.Index, m.Length, dateTime, utcOffset); return true; } - parsed_time = new ParsedDateTime(-1, -1, m.Index, m.Length, date_time); + parsedTime = new ParsedDateTime(-1, -1, m.Index, m.Length, dateTime); //} //catch(Exception e) //{ @@ -448,17 +444,17 @@ namespace DateTimeRoutines } /// - /// Tries to find date within the passed string and return it as ParsedDateTime object. + /// Tries to find date within the passed string and return it as ParsedDateTime object. /// It recognizes only date while ignoring time, so time in the returned ParsedDateTime is always 0:0:0. - /// If year of the date was not found then it accepts the current year. + /// If year of the date was not found then it accepts the current year. /// /// string that contains date - /// format to be used preferably in ambivalent instances - /// parsed date output + /// format to be used preferably in ambivalent instances + /// parsed date output /// true if date was found, else false - public static bool TryParseDate(this string str, DateTimeFormat default_format, out ParsedDateTime parsed_date) + public static bool TryParseDate(this string str, DateTimeFormat defaultFormat, out ParsedDateTime parsedDate) { - parsed_date = null; + parsedDate = null; if (string.IsNullOrEmpty(str)) return false; @@ -468,17 +464,17 @@ namespace DateTimeRoutines if (m.Success) { DateTime date; - if ((default_format ^ DateTimeFormat.USA_DATE) == DateTimeFormat.USA_DATE) + if ((defaultFormat ^ DateTimeFormat.UsaDate) == DateTimeFormat.UsaDate) { - if (!convert_to_date(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["day"].Value), int.Parse(m.Groups["month"].Value), out date)) + if (!ConvertToDate(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["day"].Value), int.Parse(m.Groups["month"].Value), out date)) return false; } else { - if (!convert_to_date(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["month"].Value), int.Parse(m.Groups["day"].Value), out date)) + if (!ConvertToDate(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["month"].Value), int.Parse(m.Groups["day"].Value), out date)) return false; } - parsed_date = new ParsedDateTime(m.Index, m.Length, -1, -1, date); + parsedDate = new ParsedDateTime(m.Index, m.Length, -1, -1, date); return true; } @@ -486,9 +482,9 @@ namespace DateTimeRoutines m = Regex.Match(str, @"(?<=^|[^\d])(?'year'\d{2}|\d{4})\s*(?'separator'[\-])\s*(?'month'\d{1,2})\s*\'separator'+\s*(?'day'\d{1,2})(?=$|[^\d])", RegexOptions.Compiled | RegexOptions.IgnoreCase); if (m.Success) { - if (!convert_to_date(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["month"].Value), int.Parse(m.Groups["day"].Value), out var date)) + if (!ConvertToDate(int.Parse(m.Groups["year"].Value), int.Parse(m.Groups["month"].Value), int.Parse(m.Groups["day"].Value), out var date)) return false; - parsed_date = new ParsedDateTime(m.Index, m.Length, -1, -1, date); + parsedDate = new ParsedDateTime(m.Index, m.Length, -1, -1, date); return true; } @@ -509,8 +505,8 @@ namespace DateTimeRoutines if (m.Success) { var month = -1; - var index_of_date = m.Index; - var length_of_date = m.Length; + var indexOfDate = m.Index; + var lengthOfDate = m.Length; switch (m.Groups["month"].Value) { @@ -563,22 +559,19 @@ namespace DateTimeRoutines break; } - int year; - if (!string.IsNullOrEmpty(m.Groups["year"].Value)) - year = int.Parse(m.Groups["year"].Value); - else - year = DefaultDate.Year; + var year = !string.IsNullOrEmpty(m.Groups["year"].Value) ? + int.Parse(m.Groups["year"].Value) : DefaultDate.Year; - if (!convert_to_date(year, month, int.Parse(m.Groups["day"].Value), out var date)) + if (!ConvertToDate(year, month, int.Parse(m.Groups["day"].Value), out var date)) return false; - parsed_date = new ParsedDateTime(index_of_date, length_of_date, -1, -1, date); + parsedDate = new ParsedDateTime(indexOfDate, lengthOfDate, -1, -1, date); return true; } return false; } - private static bool convert_to_date(int year, int month, int day, out DateTime date) + private static bool ConvertToDate(int year, int month, int day, out DateTime date) { if (year >= 100) { diff --git a/src/Jackett.Common/Indexers/CardigannIndexer.cs b/src/Jackett.Common/Indexers/CardigannIndexer.cs index ef054df4a..1123798f8 100644 --- a/src/Jackett.Common/Indexers/CardigannIndexer.cs +++ b/src/Jackett.Common/Indexers/CardigannIndexer.cs @@ -990,7 +990,7 @@ namespace Jackett.Common.Indexers try { var Date = DateTimeUtil.ParseDateTimeGoLang(Data, layout); - Data = Date.ToString(DateTimeUtil.RFC1123ZPattern); + Data = Date.ToString(DateTimeUtil.Rfc1123ZPattern); } catch (FormatException ex) { @@ -1056,10 +1056,10 @@ namespace Jackett.Common.Indexers break; case "timeago": case "reltime": - Data = DateTimeUtil.FromTimeAgo(Data).ToString(DateTimeUtil.RFC1123ZPattern); + Data = DateTimeUtil.FromTimeAgo(Data).ToString(DateTimeUtil.Rfc1123ZPattern); break; case "fuzzytime": - Data = DateTimeUtil.FromUnknown(Data).ToString(DateTimeUtil.RFC1123ZPattern); + Data = DateTimeUtil.FromUnknown(Data).ToString(DateTimeUtil.Rfc1123ZPattern); break; case "validfilename": Data = StringUtil.MakeValidFileName(Data, '_', false); @@ -1509,7 +1509,7 @@ namespace Jackett.Common.Indexers break; case "date": release.PublishDate = DateTimeUtil.FromUnknown(value); - value = release.PublishDate.ToString(DateTimeUtil.RFC1123ZPattern); + value = release.PublishDate.ToString(DateTimeUtil.Rfc1123ZPattern); break; case "files": release.Files = ParseUtil.CoerceLong(value); diff --git a/src/Jackett.Common/Utils/DateTimeUtil.cs b/src/Jackett.Common/Utils/DateTimeUtil.cs index 97c2c07c7..8ecad01cc 100644 --- a/src/Jackett.Common/Utils/DateTimeUtil.cs +++ b/src/Jackett.Common/Utils/DateTimeUtil.cs @@ -6,18 +6,26 @@ namespace Jackett.Common.Utils { public static class DateTimeUtil { - public static string RFC1123ZPattern = "ddd, dd MMM yyyy HH':'mm':'ss z"; + public const string Rfc1123ZPattern = "ddd, dd MMM yyyy HH':'mm':'ss z"; + + private static readonly Regex _TimeAgoRegexp = new Regex(@"(?i)\bago", RegexOptions.Compiled); + private static readonly Regex _TodayRegexp = new Regex(@"(?i)\btoday([\s,]*|$)", RegexOptions.Compiled); + private static readonly Regex _TomorrowRegexp = new Regex(@"(?i)\btomorrow([\s,]*|$)", RegexOptions.Compiled); + private static readonly Regex _YesterdayRegexp = new Regex(@"(?i)\byesterday([\s,]*|$)", RegexOptions.Compiled); + private static readonly Regex _DaysOfWeekRegexp = new Regex(@"(?i)\b(monday|tuesday|wednesday|thursday|friday|saturday|sunday)\s+at\s+", RegexOptions.Compiled); + private static readonly Regex _MissingYearRegexp = new Regex(@"^(\d{1,2}-\d{1,2})(\s|$)", RegexOptions.Compiled); + private static readonly Regex _MissingYearRegexp2 = new Regex(@"^(\d{1,2}\s+\w{3})\s+(\d{1,2}\:\d{1,2}.*)$", RegexOptions.Compiled); // 1 Jan 10:30 public static DateTime UnixTimestampToDateTime(long unixTime) { - var dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); + var dt = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); dt = dt.AddSeconds(unixTime).ToLocalTime(); return dt; } public static DateTime UnixTimestampToDateTime(double unixTime) { - var unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc); + var unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); var unixTimeStampInTicks = (long)(unixTime * TimeSpan.TicksPerSecond); return new DateTime(unixStart.Ticks + unixTimeStampInTicks); } @@ -35,25 +43,21 @@ namespace Jackett.Common.Utils { str = str.ToLowerInvariant(); if (str.Contains("now")) - { return DateTime.SpecifyKind(DateTime.Now, DateTimeKind.Local); - } str = str.Replace(",", ""); str = str.Replace("ago", ""); str = str.Replace("and", ""); var timeAgo = TimeSpan.Zero; - var TimeagoRegex = new Regex(@"\s*?([\d\.]+)\s*?([^\d\s\.]+)\s*?"); - var TimeagoMatches = TimeagoRegex.Match(str); + var timeagoRegex = new Regex(@"\s*?([\d\.]+)\s*?([^\d\s\.]+)\s*?"); + var timeagoMatches = timeagoRegex.Match(str); - while (TimeagoMatches.Success) + while (timeagoMatches.Success) { - var expanded = string.Empty; - - var val = ParseUtil.CoerceFloat(TimeagoMatches.Groups[1].Value); - var unit = TimeagoMatches.Groups[2].Value; - TimeagoMatches = TimeagoMatches.NextMatch(); + var val = ParseUtil.CoerceFloat(timeagoMatches.Groups[1].Value); + var unit = timeagoMatches.Groups[2].Value; + timeagoMatches = timeagoMatches.NextMatch(); if (unit.Contains("sec") || unit == "s") timeAgo += TimeSpan.FromSeconds(val); @@ -70,77 +74,37 @@ namespace Jackett.Common.Utils else if (unit.Contains("year") || unit == "y") timeAgo += TimeSpan.FromDays(val * 365); else - { throw new Exception("TimeAgo parsing failed, unknown unit: " + unit); - } } return DateTime.SpecifyKind(DateTime.Now - timeAgo, DateTimeKind.Local); } - public static TimeSpan ParseTimeSpan(string time) - { - if (string.IsNullOrWhiteSpace(time)) - return TimeSpan.Zero; - - var offset = TimeSpan.Zero; - if (time.EndsWith("AM")) - { - time = time.Substring(0, time.Length - 2); - if (time.StartsWith("12")) // 12:15 AM becomes 00:15 - time = "00" + time.Substring(2); - } - else if (time.EndsWith("PM")) - { - time = time.Substring(0, time.Length - 2); - offset = TimeSpan.FromHours(12); - } - - var ts = TimeSpan.Parse(time); - ts += offset; - return ts; - } - // Uses the DateTimeRoutines library to parse the date // http://www.codeproject.com/Articles/33298/C-Date-Time-Parser public static DateTime FromFuzzyTime(string str, string format = null) { - var dt_format = DateTimeRoutines.DateTimeRoutines.DateTimeFormat.USA_DATE; - if (format == "UK") - { - dt_format = DateTimeRoutines.DateTimeRoutines.DateTimeFormat.UK_DATE; - } + var dtFormat = format == "UK" ? + DateTimeRoutines.DateTimeRoutines.DateTimeFormat.UkDate : + DateTimeRoutines.DateTimeRoutines.DateTimeFormat.UsaDate; - if (DateTimeRoutines.DateTimeRoutines.TryParseDateOrTime(str, dt_format, out - DateTimeRoutines.DateTimeRoutines.ParsedDateTime dt)) - { + if (DateTimeRoutines.DateTimeRoutines.TryParseDateOrTime( + str, dtFormat, out DateTimeRoutines.DateTimeRoutines.ParsedDateTime dt)) return dt.DateTime; - } + throw new Exception("FromFuzzyTime parsing failed"); } - public static Regex timeAgoRegexp = new Regex(@"(?i)\bago", RegexOptions.Compiled); - public static Regex todayRegexp = new Regex(@"(?i)\btoday([\s,]*|$)", RegexOptions.Compiled); - public static Regex tomorrowRegexp = new Regex(@"(?i)\btomorrow([\s,]*|$)", RegexOptions.Compiled); - public static Regex yesterdayRegexp = new Regex(@"(?i)\byesterday([\s,]*|$)", RegexOptions.Compiled); - public static Regex daysOfWeekRegexp = new Regex(@"(?i)\b(monday|tuesday|wednesday|thursday|friday|saturday|sunday)\s+at\s+", RegexOptions.Compiled); - public static Regex missingYearRegexp = new Regex(@"^(\d{1,2}-\d{1,2})(\s|$)", RegexOptions.Compiled); - public static Regex missingYearRegexp2 = new Regex(@"^(\d{1,2}\s+\w{3})\s+(\d{1,2}\:\d{1,2}.*)$", RegexOptions.Compiled); // 1 Jan 10:30 - public static DateTime FromUnknown(string str, string format = null) { try { str = ParseUtil.NormalizeSpace(str); - Match match; - if (str.ToLower().Contains("now")) - { return DateTime.UtcNow; - } // ... ago - match = timeAgoRegexp.Match(str); + var match = _TimeAgoRegexp.Match(str); if (match.Success) { var timeago = str; @@ -148,7 +112,7 @@ namespace Jackett.Common.Utils } // Today ... - match = todayRegexp.Match(str); + match = _TodayRegexp.Match(str); if (match.Success) { var time = str.Replace(match.Groups[0].Value, ""); @@ -158,7 +122,7 @@ namespace Jackett.Common.Utils } // Yesterday ... - match = yesterdayRegexp.Match(str); + match = _YesterdayRegexp.Match(str); if (match.Success) { var time = str.Replace(match.Groups[0].Value, ""); @@ -169,7 +133,7 @@ namespace Jackett.Common.Utils } // Tomorrow ... - match = tomorrowRegexp.Match(str); + match = _TomorrowRegexp.Match(str); if (match.Success) { var time = str.Replace(match.Groups[0].Value, ""); @@ -180,14 +144,14 @@ namespace Jackett.Common.Utils } // [day of the week] at ... (eg: Saturday at 14:22) - match = daysOfWeekRegexp.Match(str); + match = _DaysOfWeekRegexp.Match(str); if (match.Success) { var time = str.Replace(match.Groups[0].Value, ""); var dt = DateTime.SpecifyKind(DateTime.UtcNow.Date, DateTimeKind.Unspecified); dt += ParseTimeSpan(time); - var dow = DayOfWeek.Monday; + DayOfWeek dow; var groupMatchLower = match.Groups[1].Value.ToLower(); if (groupMatchLower.StartsWith("monday")) dow = DayOfWeek.Monday; @@ -221,28 +185,28 @@ namespace Jackett.Common.Utils } // add missing year - match = missingYearRegexp.Match(str); + match = _MissingYearRegexp.Match(str); if (match.Success) { var date = match.Groups[1].Value; - var newDate = DateTime.Now.Year.ToString() + "-" + date; + var newDate = DateTime.Now.Year + "-" + date; str = str.Replace(date, newDate); } // add missing year 2 - match = missingYearRegexp2.Match(str); + match = _MissingYearRegexp2.Match(str); if (match.Success) { var date = match.Groups[1].Value; var time = match.Groups[2].Value; - str = date + " " + DateTime.Now.Year.ToString() + " " + time; + str = date + " " + DateTime.Now.Year + " " + time; } return FromFuzzyTime(str, format); } catch (Exception ex) { - throw new Exception(string.Format("DateTime parsing failed for \"{0}\": {1}", str, ex.ToString())); + throw new Exception($"DateTime parsing failed for \"{str}\": {ex}"); } } @@ -319,8 +283,32 @@ namespace Jackett.Common.Utils } catch (FormatException ex) { - throw new FormatException(string.Format("Error while parsing DateTime \"{0}\", using layout \"{1}\" ({2}): {3}", date, layout, pattern, ex.Message)); + throw new FormatException($"Error while parsing DateTime \"{date}\", using layout \"{layout}\" ({pattern}): {ex.Message}"); } } + + private static TimeSpan ParseTimeSpan(string time) + { + if (string.IsNullOrWhiteSpace(time)) + return TimeSpan.Zero; + + var offset = TimeSpan.Zero; + if (time.EndsWith("AM")) + { + time = time.Substring(0, time.Length - 2); + if (time.StartsWith("12")) // 12:15 AM becomes 00:15 + time = "00" + time.Substring(2); + } + else if (time.EndsWith("PM")) + { + time = time.Substring(0, time.Length - 2); + offset = TimeSpan.FromHours(12); + } + + var ts = TimeSpan.Parse(time); + ts += offset; + return ts; + } + } }