From 0c55700aa82d17c11e0e32445a2282b99f13328a Mon Sep 17 00:00:00 2001 From: Mark Date: Sat, 29 Jul 2023 16:41:29 +0800 Subject: [PATCH] Timezone fixes --- TVRename/Exporter/MissingCSV.cs | 2 +- TVRename/Exporter/MissingXML.cs | 2 +- TVRename/Exporter/UpcomingRSS.cs | 2 +- TVRename/Exporter/UpcomingTXT.cs | 2 +- TVRename/Exporter/UpcomingXML.cs | 2 +- TVRename/Exporter/UpcomingiCAL.cs | 2 +- TVRename/Forms/UI.cs | 8 ++-- TVRename/ItemsAndActions/Item.cs | 4 +- TVRename/Model/CachePersistorMapping.cs | 2 +- TVRename/Model/CachedSeriesInfo.cs | 12 ++--- TVRename/Model/Episode.cs | 7 +-- TVRename/ScanActivity/Finders/FinderHelper.cs | 2 +- .../ScanShowActivity/CheckAllFoldersExist.cs | 2 +- .../ScanShowActivity/RenameAndMissingCheck.cs | 2 +- TVRename/Settings/CustomEpisodeName.cs | 9 ++-- TVRename/Settings/ProcessedEpisode.cs | 46 ++++--------------- TVRename/Settings/ProcessedSeason.cs | 10 ++-- TVRename/Sources/TMDB/LocalCache.cs | 2 - TVRename/TVRename/ShowLibrary.cs | 15 +++--- .../Extensions/EnumerableExtensions.cs | 5 ++ TVRename/Utility/Helper/ShowHtmlHelper.cs | 6 +-- TVRename/Utility/PossibleMergedEpisode.cs | 4 +- TVRename/Utility/Sorters/DateSorterWTW.cs | 2 +- 23 files changed, 63 insertions(+), 87 deletions(-) diff --git a/TVRename/Exporter/MissingCSV.cs b/TVRename/Exporter/MissingCSV.cs index 5da0bee8f..e2e43649c 100644 --- a/TVRename/Exporter/MissingCSV.cs +++ b/TVRename/Exporter/MissingCSV.cs @@ -35,7 +35,7 @@ protected override void Do() foreach (ShowItemMissing? im in TheActionList.MissingEpisodes) { ProcessedEpisode pe = im.MissingEpisode; - DateTime? dt = pe.GetAirDateDt(true); + DateTime? dt = pe.GetAirDateDt(); file.WriteLine( $"{pe.TheCachedSeries.Name.InDoubleQuotes()},{pe.AppropriateSeasonNumber},{pe.EpisodeNumbersAsText},{pe.Name.InDoubleQuotes()},{dt:G},{im.TargetFolder.InDoubleQuotes()},{im.Filename.InDoubleQuotes()},{pe.SeriesId}"); } diff --git a/TVRename/Exporter/MissingXML.cs b/TVRename/Exporter/MissingXML.cs index 4074d4c3b..176c141db 100644 --- a/TVRename/Exporter/MissingXML.cs +++ b/TVRename/Exporter/MissingXML.cs @@ -68,7 +68,7 @@ protected override void Do() writer.WriteElement("description", missing.MissingEpisode.Overview); writer.WriteStartElement("pubDate"); - DateTime? dt = missing.MissingEpisode.GetAirDateDt(true); + DateTime? dt = missing.MissingEpisode.GetAirDateDt(); if (dt != null) { writer.WriteValue(dt.Value.ToString("F")); diff --git a/TVRename/Exporter/UpcomingRSS.cs b/TVRename/Exporter/UpcomingRSS.cs index abebe36ea..ad7f84ab3 100644 --- a/TVRename/Exporter/UpcomingRSS.cs +++ b/TVRename/Exporter/UpcomingRSS.cs @@ -60,7 +60,7 @@ protected override bool Generate(System.IO.Stream str, IEnumerable" + niceName + "
" + ei.Overview); writer.WriteStartElement("pubDate"); - DateTime? dt = ei.GetAirDateDt(true); + DateTime? dt = ei.GetAirDateDt(); if (dt != null) { writer.WriteValue(dt.Value.ToString("r")); diff --git a/TVRename/Exporter/UpcomingTXT.cs b/TVRename/Exporter/UpcomingTXT.cs index c023a3179..f403e0555 100644 --- a/TVRename/Exporter/UpcomingTXT.cs +++ b/TVRename/Exporter/UpcomingTXT.cs @@ -40,7 +40,7 @@ protected override bool Generate(System.IO.Stream str, IEnumerable SeasonNumberAsInt?.Pad(2) + "-" + Episode?.AppropriateEpNum.Pad(4) + "-" + AirDateString; - public virtual string AirDateString => Episode?.GetAirDateDt(true).PrettyPrint() ?? Movie?.CachedMovie?.FirstAired.PrettyPrint() ?? string.Empty; + public virtual string AirDateString => Episode?.GetAirDateDt().PrettyPrint() ?? Movie?.CachedMovie?.FirstAired.PrettyPrint() ?? string.Empty; - public virtual DateTime? AirDate => Episode?.GetAirDateDt(true) ?? Movie?.CachedMovie?.FirstAired; + public virtual DateTime? AirDate => Episode?.GetAirDateDt() ?? Movie?.CachedMovie?.FirstAired; public abstract string? DestinationFolder { get; } public abstract string? DestinationFile { get; } diff --git a/TVRename/Model/CachePersistorMapping.cs b/TVRename/Model/CachePersistorMapping.cs index 74164349a..14428f6e5 100644 --- a/TVRename/Model/CachePersistorMapping.cs +++ b/TVRename/Model/CachePersistorMapping.cs @@ -29,7 +29,7 @@ public static void WriteEpisodeXml(this XmlWriter writer, Episode e) writer.WriteElement("FirstAired", e.FirstAired?.ToString("yyyy-MM-dd", CultureInfo.InvariantCulture), true); writer.WriteElement("AirTime", e.AirTime?.ToString("HH:mm"), true); - writer.WriteElement("AirTime", e.AirStamp); + writer.WriteElement("AirStamp", e.AirStamp); writer.WriteElement("DvdChapter", e.DvdChapter); writer.WriteElement("DvdDiscId", e.DvdDiscId, true); diff --git a/TVRename/Model/CachedSeriesInfo.cs b/TVRename/Model/CachedSeriesInfo.cs index a2862bdf5..1111ebefb 100644 --- a/TVRename/Model/CachedSeriesInfo.cs +++ b/TVRename/Model/CachedSeriesInfo.cs @@ -35,18 +35,18 @@ public class CachedSeriesInfo : CachedMediaInfo public int? MinYear => Episodes .Where(e => !e.IsSpecial(SeasonOrderType)) - .Select(e => e.GetAirDateDt()) + .Select(e => e.Year) .Where(adt => adt.HasValue) - .Select(adt => adt!.Value) - .Min(airDateTime => (int?)airDateTime.Year); + .MinOrNull(adt => adt!.Value) + ; public int? MaxYear => Episodes .Where(e => !e.IsSpecial(SeasonOrderType)) - .Select(e => e.GetAirDateDt()) + .Select(e => e.Year) .Where(adt => adt.HasValue) - .Select(adt => adt!.Value) - .Max(airDateTime => (int?)airDateTime.Year); + .MaxOrNull(adt => adt!.Value) + ; public string Year => FirstAired?.Year.ToString() ?? $"{MinYear}"; diff --git a/TVRename/Model/Episode.cs b/TVRename/Model/Episode.cs index ab8fb8a83..e65e27f59 100644 --- a/TVRename/Model/Episode.cs +++ b/TVRename/Model/Episode.cs @@ -90,7 +90,7 @@ protected Episode(Episode o) AirTime = o.AirTime; } - public LocalDateTime? GetAirDateDt() + public LocalDateTime? LocalAirTime() { DateTime? fa = FirstAired; @@ -109,7 +109,7 @@ protected Episode(Episode o) public DateTime? GetAirDateDt(DateTimeZone tz) { - LocalDateTime? dt = GetAirDateDt(); + LocalDateTime? dt = LocalAirTime(); if (dt is null) { return null; @@ -186,6 +186,7 @@ public CachedSeriesInfo TheCachedSeries } } + public int? Year => LocalAirTime()?.Year; public bool Ok() { bool returnVal = EpisodeId != -1 && AiredEpNum != -1 && SeasonId != -1 && ReadAiredSeasonNum != -1; @@ -259,7 +260,7 @@ public void SetDirectors(List directors) public bool HasAired() { - LocalDateTime? dateTime = GetAirDateDt(); + LocalDateTime? dateTime = LocalAirTime(); return dateTime.HasValue && dateTime.Value.InUtc().ToInstant().CompareTo(SystemClock.Instance.GetCurrentInstant()) < 0; } diff --git a/TVRename/ScanActivity/Finders/FinderHelper.cs b/TVRename/ScanActivity/Finders/FinderHelper.cs index 36c6dd6c0..d8cc94459 100644 --- a/TVRename/ScanActivity/Finders/FinderHelper.cs +++ b/TVRename/ScanActivity/Finders/FinderHelper.cs @@ -129,7 +129,7 @@ public static bool FindSeasEpDateCheck(string? filename, out int seas, out int e foreach (Episode epi in si.EpisodesToUse()) { - LocalDateTime? dt = epi.GetAirDateDt(); // file will have local timezone date, not ours + LocalDateTime? dt = epi.LocalAirTime(); // file will have local timezone date, not ours if (dt is null) { continue; diff --git a/TVRename/ScanActivity/ScanShowActivity/CheckAllFoldersExist.cs b/TVRename/ScanActivity/ScanShowActivity/CheckAllFoldersExist.cs index 54657711b..104a9ec9a 100644 --- a/TVRename/ScanActivity/ScanShowActivity/CheckAllFoldersExist.cs +++ b/TVRename/ScanActivity/ScanShowActivity/CheckAllFoldersExist.cs @@ -91,7 +91,7 @@ private static bool MightWeProcess(ProcessedEpisode episode, IEnumerable } } - if (!episode.Show.ForceCheckNoAirdate && episode.GetAirDateDt(true) == null) + if (!episode.Show.ForceCheckNoAirdate && episode.GetAirDateDt() == null) { return false; } diff --git a/TVRename/ScanActivity/ScanShowActivity/RenameAndMissingCheck.cs b/TVRename/ScanActivity/ScanShowActivity/RenameAndMissingCheck.cs index 51aabba3a..cff9686df 100644 --- a/TVRename/ScanActivity/ScanShowActivity/RenameAndMissingCheck.cs +++ b/TVRename/ScanActivity/ScanShowActivity/RenameAndMissingCheck.cs @@ -325,7 +325,7 @@ private void AddMissingIfNeeded(ShowConfiguration si, int snum, string folder, b // second part of missing check is to see what is missing! if (missCheck) { - DateTime? dt = episode.GetAirDateDt(true); + DateTime? dt = episode.GetAirDateDt(); bool dtOk = dt != null; bool notFuture = diff --git a/TVRename/Settings/CustomEpisodeName.cs b/TVRename/Settings/CustomEpisodeName.cs index e16d6d1f5..f1539948c 100644 --- a/TVRename/Settings/CustomEpisodeName.cs +++ b/TVRename/Settings/CustomEpisodeName.cs @@ -10,6 +10,7 @@ using System; using System.Collections.Generic; using System.Text.RegularExpressions; +using NodaTime; // This builds the filenames to rename to, for any given episode (or multi-episode episode) @@ -169,7 +170,7 @@ private string GetTargetEpisodeName(ShowConfiguration show, Episode ep, bool url ProcessedSeason? selectedProcessedSeason = show.GetSeason(ep.GetSeasonNumber(show.Order)); name = name.ReplaceInsensitive("{SeasonYear}", selectedProcessedSeason != null ? selectedProcessedSeason.MinYear().ToString() : string.Empty); - name = ReplaceDates(urlEncode, name, ep.GetAirDateDt(show.GetTimeZone())); + name = ReplaceDates(urlEncode, name, ep.LocalAirTime()); name = Regex.Replace(name, "([^\\\\])\\[.*?[^\\\\]\\]", "$1"); // remove optional parts @@ -179,7 +180,7 @@ private string GetTargetEpisodeName(ShowConfiguration show, Episode ep, bool url return name.Trim(); } - private static string ReplaceDates(bool urlEncode, string name, DateTime? airdt) + private static string ReplaceDates(bool urlEncode, string name, LocalDateTime? airdt) { if (!name.Contains("{ShortDate}") && !name.Contains("{LongDate}") && !name.Contains("{YMDDate}")) { @@ -193,7 +194,7 @@ private static string ReplaceDates(bool urlEncode, string name, DateTime? airdt) if (airdt != null) { - DateTime dt = (DateTime)airdt; + DateTime dt = airdt.Value.ToDateTimeUnspecified(); name = name.ReplaceInsensitive("{ShortDate}", dt.ToString("d")); name = name.ReplaceInsensitive("{LongDate}", dt.ToString("D")); ymd = dt.ToString("yyyy/MM/dd"); @@ -264,7 +265,7 @@ public static string NameForNoExt(ProcessedEpisode pe, string styleString, bool name = name.ReplaceInsensitive("{Imdb}", pe.ImdbCode); name = name.ReplaceInsensitive("{ShowImdb}", pe.Show.CachedShow?.Imdb ?? string.Empty); - name = ReplaceDates(urlEncode, name, pe.GetAirDateDt(false)); + name = ReplaceDates(urlEncode, name, pe.LocalAirTime()); name = Regex.Replace(name, "{AllEpisodes}", AllEpsText(pe), RegexOptions.IgnoreCase); // ReSharper disable once ConvertIfStatementToConditionalTernaryExpression diff --git a/TVRename/Settings/ProcessedEpisode.cs b/TVRename/Settings/ProcessedEpisode.cs index 337186389..3a49e6543 100644 --- a/TVRename/Settings/ProcessedEpisode.cs +++ b/TVRename/Settings/ProcessedEpisode.cs @@ -1,4 +1,3 @@ -using NodaTime; using System; using System.Collections.Generic; @@ -135,18 +134,7 @@ public ProcessedEpisode(ProcessedEpisode pe, ShowConfiguration si, string name, public string SeasonNumberAsText => TVSettings.SeasonNameFor(AppropriateSeasonNumber); - public string? WebsiteUrl - { - get - { - if (Show.Provider == TVDoc.ProviderType.TheTVDB) - { - return TVDBWebsiteUrl; - } - - return LinkUrl; - } - } + public string? WebsiteUrl => Show.Provider == TVDoc.ProviderType.TheTVDB ? TVDBWebsiteUrl : LinkUrl; public string EpisodeNumbersAsText { @@ -178,27 +166,13 @@ public static int DVDOrderSorter(ProcessedEpisode e1, ProcessedEpisode e2) return ep1 - ep2; } - public DateTime? GetAirDateDt(bool inLocalTime) - { - LocalDateTime? x = GetAirDateDt(); - - if (!inLocalTime && x.HasValue) - { - return x.Value.ToDateTimeUnspecified(); - } - - if (!inLocalTime) - { - return null; - } - + public DateTime? GetAirDateDt() => // do timezone adjustment - return GetAirDateDt(Show.GetTimeZone()); - } + GetAirDateDt(Show.GetTimeZone()); public string HowLong() { - DateTime? airsdt = GetAirDateDt(true); + DateTime? airsdt = GetAirDateDt(); if (airsdt is null) { return string.Empty; @@ -226,26 +200,26 @@ public string HowLong() public string DayOfWeek() { - DateTime? dt = GetAirDateDt(true); + DateTime? dt = GetAirDateDt(); return dt != null ? dt.Value.ToString("ddd") : "-"; } public string TimeOfDay() { - DateTime? dt = GetAirDateDt(true); + DateTime? dt = GetAirDateDt(); return dt != null ? dt.Value.ToString("t") : "-"; } public new bool HasAired() { - DateTime? airsdt = GetAirDateDt(true); + DateTime? airsdt = GetAirDateDt(); TimeSpan? ts = airsdt?.Subtract(DateTime.Now); // how long... return ts?.TotalHours < 0; } public bool WithinLastDays(int days) { - DateTime? dt = GetAirDateDt(true); + DateTime? dt = GetAirDateDt(); if (dt is null || dt.Value.CompareTo(DateTime.MaxValue) == 0) { return false; @@ -259,7 +233,7 @@ public bool WithinLastDays(int days) public bool IsInFuture(bool def) { - DateTime? airsdt = GetAirDateDt(true); + DateTime? airsdt = GetAirDateDt(); if (airsdt is null) { return def; @@ -294,7 +268,7 @@ public bool NotOnDvd() public bool HasAiredDate() { - DateTime? dt = GetAirDateDt(true); + DateTime? dt = GetAirDateDt(); return dt != null && dt.Value.CompareTo(DateTime.MaxValue) != 0; } } diff --git a/TVRename/Settings/ProcessedSeason.cs b/TVRename/Settings/ProcessedSeason.cs index efc4d3c1a..3669f2843 100644 --- a/TVRename/Settings/ProcessedSeason.cs +++ b/TVRename/Settings/ProcessedSeason.cs @@ -108,19 +108,17 @@ public SeasonStatus Status(DateTimeZone tz) internal int MinYear() { return Episodes.Values - .Select(e => e.GetAirDateDt()) + .Select(e => e.Year) .Where(adt => adt.HasValue) - .Select(adt => adt!.Value) - .MinOrDefault(airDateTime => airDateTime.Year, 9999); + .MinOrDefault(adt => adt!.Value, 9999); } internal int MaxYear() { return Episodes.Values - .Select(e => e.GetAirDateDt()) + .Select(e => e.Year) .Where(adt => adt.HasValue) - .Select(adt => adt!.Value) - .MaxOrDefault(airDateTime => airDateTime.Year, 0); + .MaxOrDefault(adt => adt!.Value, 0); } private bool HasEpisodes => !Episodes.IsEmpty; diff --git a/TVRename/Sources/TMDB/LocalCache.cs b/TVRename/Sources/TMDB/LocalCache.cs index 3fcbd666d..7bdd2ce13 100644 --- a/TVRename/Sources/TMDB/LocalCache.cs +++ b/TVRename/Sources/TMDB/LocalCache.cs @@ -777,8 +777,6 @@ private static void AddSeasons(ISeriesSpecifier ss, TvShow downloadedSeries, Cac { Name = downloadedEpisode.Name, Overview = downloadedEpisode.Overview, - AirTime = downloadedEpisode.AirDate, - AirStamp = downloadedEpisode.AirDate, FirstAired = downloadedEpisode.AirDate, AiredEpNum = downloadedEpisode.EpisodeNumber, AiredSeasonNumber = downloadedEpisode.SeasonNumber, diff --git a/TVRename/TVRename/ShowLibrary.cs b/TVRename/TVRename/ShowLibrary.cs index 1993b1339..e173766a3 100644 --- a/TVRename/TVRename/ShowLibrary.cs +++ b/TVRename/TVRename/ShowLibrary.cs @@ -678,7 +678,7 @@ public List NextNShows(int nShows, int nDaysPast, int nDaysFut return found; } - DateTime? nextdt = nextAfterThat.GetAirDateDt(true); + DateTime? nextdt = nextAfterThat.GetAirDateDt(); if (nextdt.HasValue) { notBefore = nextdt.Value; @@ -721,7 +721,7 @@ public List NextNShows(int nShows, int nDaysPast, int nDaysFut continue; } - DateTime? airdt = ei.GetAirDateDt(true); + DateTime? airdt = ei.GetAirDateDt(); if (airdt is null || airdt == DateTime.MaxValue) { @@ -759,6 +759,8 @@ public List NextNShows(int nShows, int nDaysPast, int nDaysFut public IEnumerable GetRecentAndFutureEps(int recentDays) { List returnList = new(); + DateTime now = DateTime.Now; + DateTime limit = now.AddDays(-recentDays); foreach (ShowConfiguration si in Shows) { @@ -767,19 +769,16 @@ public IEnumerable GetRecentAndFutureEps(int recentDays) continue; } - DateTime now = DateTime.Now; - DateTime limit = now.AddDays(-recentDays); - foreach (List eis in si.ActiveSeasons.Select(p => p.Value)) { bool nextToAirFound = false; foreach (ProcessedEpisode ei in eis .Where(ei=>ei.HasAiredDate()) - .Where(ei=>ei.GetAirDateDt(true)>=limit) - .OrderBy(ei=>ei.GetAirDateDt(true))) + .Where(ei=>ei.GetAirDateDt()>=limit) + .OrderBy(ei=>ei.GetAirDateDt())) { - DateTime? dt = ei.GetAirDateDt(true); + DateTime? dt = ei.GetAirDateDt(); if (dt>now && !nextToAirFound) { diff --git a/TVRename/Utility/Extensions/EnumerableExtensions.cs b/TVRename/Utility/Extensions/EnumerableExtensions.cs index 8a992ede3..4cb8c1819 100644 --- a/TVRename/Utility/Extensions/EnumerableExtensions.cs +++ b/TVRename/Utility/Extensions/EnumerableExtensions.cs @@ -81,4 +81,9 @@ public static int MinOrDefault(this IEnumerable enumeration, Func return list.Any() ? list.Min(selector) : null; } + public static TProp? MaxOrNull(this IEnumerable @this, Func selector) where TProp : struct + { + IEnumerable list = @this.ToList(); + return list.Any() ? list.Max(selector) : null; + } } diff --git a/TVRename/Utility/Helper/ShowHtmlHelper.cs b/TVRename/Utility/Helper/ShowHtmlHelper.cs index 9f900de21..d5ee356ba 100644 --- a/TVRename/Utility/Helper/ShowHtmlHelper.cs +++ b/TVRename/Utility/Helper/ShowHtmlHelper.cs @@ -1072,7 +1072,7 @@ private static string SeasonSummaryTableRow(ProcessedEpisode ep, bool includeDir } string airedText = ep.HasAired() ? " (Aired)" : string.Empty; - DateTime? airDateDt = ep.GetAirDateDt(true); + DateTime? airDateDt = ep.GetAirDateDt(); string airDateString = airDateDt.HasValue && airDateDt > DateTime.MinValue ? airDateDt.Value.ToString("d", DateTimeFormatInfo.CurrentInfo) : string.Empty; @@ -1350,7 +1350,7 @@ private static string DateDetailsHtml(this ProcessedEpisode ei) { try { - DateTime? dt = ei.GetAirDateDt(true); + DateTime? dt = ei.GetAirDateDt(); if (dt != null && dt.Value.CompareTo(DateTime.MaxValue) != 0) { return $"
{dt.Value.ToShortDateString()}
({ei.HowLong()})"; @@ -1703,7 +1703,7 @@ public static string GetSeasonHtmlOverviewOffline(this ShowConfiguration si, Pro body += " Search"; } - DateTime? dt = ei.GetAirDateDt(true); + DateTime? dt = ei.GetAirDateDt(); if (dt != null && dt.Value.CompareTo(DateTime.MaxValue) != 0) { body += "

" + dt.Value.ToShortDateString() + " (" + ei.HowLong() + ")"; diff --git a/TVRename/Utility/PossibleMergedEpisode.cs b/TVRename/Utility/PossibleMergedEpisode.cs index 0c4d65929..00948eceb 100644 --- a/TVRename/Utility/PossibleMergedEpisode.cs +++ b/TVRename/Utility/PossibleMergedEpisode.cs @@ -1,4 +1,4 @@ -// + // // Main website for TVRename is http://tvrename.com // // Source code available at https://github.com/TV-Rename/tvrename @@ -43,7 +43,7 @@ public ListViewItem PresentationView lvi.SubItems.Add(episodeOne.AppropriateSeasonNumber.ToString()); lvi.SubItems.Add(episodeOne.EpisodeNumbersAsText + " & " + episodeTwo.EpisodeNumbersAsText); - lvi.SubItems.Add(episodeOne.GetAirDateDt(true).PrettyPrint()); + lvi.SubItems.Add(episodeOne.GetAirDateDt().PrettyPrint()); lvi.SubItems.Add(episodeOne.Name + " & " + episodeTwo.Name); List names = new() { episodeOne.Name, episodeTwo.Name }; diff --git a/TVRename/Utility/Sorters/DateSorterWTW.cs b/TVRename/Utility/Sorters/DateSorterWTW.cs index 1c187edd1..eee9f2d6e 100644 --- a/TVRename/Utility/Sorters/DateSorterWTW.cs +++ b/TVRename/Utility/Sorters/DateSorterWTW.cs @@ -21,7 +21,7 @@ public DateSorterWtw(int column) : base(column) { try { - return ((ProcessedEpisode)lvi.Tag).GetAirDateDt(true); + return ((ProcessedEpisode)lvi.Tag).GetAirDateDt(); } catch {