diff --git a/CHANGELOG.md b/CHANGELOG.md index f5e7501fe..88d8d5b03 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). - Use fake image extension (`.jpg`) for artwork in M3U and XMLTV since Kodi detects MIME type from URL - Enable HEAD requests for IPTV image paths since Kodi requires those - Properly display watermark when no other video filters (like scaling or padding) are required +- Fix building some playouts in timezones with positive offsets (like UTC+2) ## [0.0.56-alpha] - 2021-09-10 ### Added diff --git a/ErsatzTV.Application/Emby/Commands/SynchronizeEmbyLibraryByIdHandler.cs b/ErsatzTV.Application/Emby/Commands/SynchronizeEmbyLibraryByIdHandler.cs index 2e6e30996..15746e238 100644 --- a/ErsatzTV.Application/Emby/Commands/SynchronizeEmbyLibraryByIdHandler.cs +++ b/ErsatzTV.Application/Emby/Commands/SynchronizeEmbyLibraryByIdHandler.cs @@ -67,7 +67,7 @@ namespace ErsatzTV.Application.Emby.Commands private async Task Synchronize(RequestParameters parameters) { - var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? DateTime.MinValue, TimeSpan.Zero); + var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? SystemTime.MinValueUtc, TimeSpan.Zero); DateTimeOffset nextScan = lastScan + TimeSpan.FromHours(parameters.LibraryRefreshInterval); if (parameters.ForceScan || nextScan < DateTimeOffset.Now) { diff --git a/ErsatzTV.Application/Jellyfin/Commands/SynchronizeJellyfinLibraryByIdHandler.cs b/ErsatzTV.Application/Jellyfin/Commands/SynchronizeJellyfinLibraryByIdHandler.cs index 6efb94c7c..ce07effc1 100644 --- a/ErsatzTV.Application/Jellyfin/Commands/SynchronizeJellyfinLibraryByIdHandler.cs +++ b/ErsatzTV.Application/Jellyfin/Commands/SynchronizeJellyfinLibraryByIdHandler.cs @@ -67,7 +67,7 @@ namespace ErsatzTV.Application.Jellyfin.Commands private async Task Synchronize(RequestParameters parameters) { - var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? DateTime.MinValue, TimeSpan.Zero); + var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? SystemTime.MinValueUtc, TimeSpan.Zero); DateTimeOffset nextScan = lastScan + TimeSpan.FromHours(parameters.LibraryRefreshInterval); if (parameters.ForceScan || nextScan < DateTimeOffset.Now) { diff --git a/ErsatzTV.Application/MediaCards/Mapper.cs b/ErsatzTV.Application/MediaCards/Mapper.cs index 1d766843c..62a2ca163 100644 --- a/ErsatzTV.Application/MediaCards/Mapper.cs +++ b/ErsatzTV.Application/MediaCards/Mapper.cs @@ -1,5 +1,6 @@ using System; using System.Linq; +using ErsatzTV.Core; using ErsatzTV.Core.Domain; using ErsatzTV.Core.Emby; using ErsatzTV.Core.Jellyfin; @@ -43,7 +44,7 @@ namespace ErsatzTV.Application.MediaCards bool isSearchResult) => new( episodeMetadata.EpisodeId, - episodeMetadata.ReleaseDate ?? DateTime.MinValue, + episodeMetadata.ReleaseDate ?? SystemTime.MinValueUtc, episodeMetadata.Episode.Season.Show.ShowMetadata.HeadOrNone().Match( m => m.Title ?? string.Empty, () => string.Empty), diff --git a/ErsatzTV.Application/MediaSources/Commands/ScanLocalLibraryHandler.cs b/ErsatzTV.Application/MediaSources/Commands/ScanLocalLibraryHandler.cs index 34d8de5a0..a420f55ee 100644 --- a/ErsatzTV.Application/MediaSources/Commands/ScanLocalLibraryHandler.cs +++ b/ErsatzTV.Application/MediaSources/Commands/ScanLocalLibraryHandler.cs @@ -78,7 +78,7 @@ namespace ErsatzTV.Application.MediaSources.Commands decimal progressMin = (decimal) i / localLibrary.Paths.Count; decimal progressMax = (decimal) (i + 1) / localLibrary.Paths.Count; - var lastScan = new DateTimeOffset(libraryPath.LastScan ?? DateTime.MinValue, TimeSpan.Zero); + var lastScan = new DateTimeOffset(libraryPath.LastScan ?? SystemTime.MinValueUtc, TimeSpan.Zero); DateTimeOffset nextScan = lastScan + TimeSpan.FromHours(libraryRefreshInterval); if (forceScan || nextScan < DateTimeOffset.Now) { diff --git a/ErsatzTV.Application/Plex/Commands/SynchronizePlexLibraryByIdHandler.cs b/ErsatzTV.Application/Plex/Commands/SynchronizePlexLibraryByIdHandler.cs index 310a988d7..49b1a91ae 100644 --- a/ErsatzTV.Application/Plex/Commands/SynchronizePlexLibraryByIdHandler.cs +++ b/ErsatzTV.Application/Plex/Commands/SynchronizePlexLibraryByIdHandler.cs @@ -65,7 +65,7 @@ namespace ErsatzTV.Application.Plex.Commands private async Task Synchronize(RequestParameters parameters) { - var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? DateTime.MinValue, TimeSpan.Zero); + var lastScan = new DateTimeOffset(parameters.Library.LastScan ?? SystemTime.MinValueUtc, TimeSpan.Zero); DateTimeOffset nextScan = lastScan + TimeSpan.FromHours(parameters.LibraryRefreshInterval); if (parameters.ForceScan || nextScan < DateTimeOffset.Now) { diff --git a/ErsatzTV.Core.Tests/Fakes/FakeFileEntry.cs b/ErsatzTV.Core.Tests/Fakes/FakeFileEntry.cs index fb824bf69..fa02434ae 100644 --- a/ErsatzTV.Core.Tests/Fakes/FakeFileEntry.cs +++ b/ErsatzTV.Core.Tests/Fakes/FakeFileEntry.cs @@ -4,6 +4,6 @@ namespace ErsatzTV.Core.Tests.Fakes { public record FakeFileEntry(string Path) { - public DateTime LastWriteTime { get; set; } = DateTime.MinValue; + public DateTime LastWriteTime { get; set; } = SystemTime.MinValueUtc; } } diff --git a/ErsatzTV.Core.Tests/Fakes/FakeLocalFileSystem.cs b/ErsatzTV.Core.Tests/Fakes/FakeLocalFileSystem.cs index 2036ace2c..f95ed4c5e 100644 --- a/ErsatzTV.Core.Tests/Fakes/FakeLocalFileSystem.cs +++ b/ErsatzTV.Core.Tests/Fakes/FakeLocalFileSystem.cs @@ -41,7 +41,7 @@ namespace ErsatzTV.Core.Tests.Fakes public DateTime GetLastWriteTime(string path) => Optional(_files.SingleOrDefault(f => f.Path == path)) .Map(f => f.LastWriteTime) - .IfNone(DateTime.MinValue); + .IfNone(SystemTime.MinValueUtc); public bool IsLibraryPathAccessible(LibraryPath libraryPath) => _files.Any(f => f.Path.StartsWith(libraryPath.Path + Path.DirectorySeparatorChar)); diff --git a/ErsatzTV.Core/Metadata/LocalFileSystem.cs b/ErsatzTV.Core/Metadata/LocalFileSystem.cs index d0183f79c..96fb316d4 100644 --- a/ErsatzTV.Core/Metadata/LocalFileSystem.cs +++ b/ErsatzTV.Core/Metadata/LocalFileSystem.cs @@ -22,7 +22,7 @@ namespace ErsatzTV.Core.Metadata } public DateTime GetLastWriteTime(string path) => - Try(File.GetLastWriteTimeUtc(path)).IfFail(() => DateTime.MinValue); + Try(File.GetLastWriteTimeUtc(path)).IfFail(() => SystemTime.MinValueUtc); public bool IsLibraryPathAccessible(LibraryPath libraryPath) => Directory.Exists(libraryPath.Path); diff --git a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs index e7dad4413..732c7ea66 100644 --- a/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs +++ b/ErsatzTV.Core/Metadata/LocalMetadataProvider.cs @@ -218,7 +218,7 @@ namespace ErsatzTV.Core.Metadata existing.Tagline = metadata.Tagline; existing.Title = metadata.Title; - if (existing.DateAdded == DateTime.MinValue) + if (existing.DateAdded == SystemTime.MinValueUtc) { existing.DateAdded = metadata.DateAdded; } @@ -318,7 +318,7 @@ namespace ErsatzTV.Core.Metadata existing.Tagline = metadata.Tagline; existing.Title = metadata.Title; - if (existing.DateAdded == DateTime.MinValue) + if (existing.DateAdded == SystemTime.MinValueUtc) { existing.DateAdded = metadata.DateAdded; } @@ -423,7 +423,7 @@ namespace ErsatzTV.Core.Metadata existing.Tagline = metadata.Tagline; existing.Title = metadata.Title; - if (existing.DateAdded == DateTime.MinValue) + if (existing.DateAdded == SystemTime.MinValueUtc) { existing.DateAdded = metadata.DateAdded; } @@ -486,7 +486,7 @@ namespace ErsatzTV.Core.Metadata existing.Disambiguation = metadata.Disambiguation; existing.Biography = metadata.Biography; - if (existing.DateAdded == DateTime.MinValue) + if (existing.DateAdded == SystemTime.MinValueUtc) { existing.DateAdded = metadata.DateAdded; } @@ -581,7 +581,7 @@ namespace ErsatzTV.Core.Metadata existing.Plot = metadata.Plot; existing.Album = metadata.Album; - if (existing.DateAdded == DateTime.MinValue) + if (existing.DateAdded == SystemTime.MinValueUtc) { existing.DateAdded = metadata.DateAdded; } diff --git a/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs b/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs index 9f7858c6d..98948785f 100644 --- a/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs +++ b/ErsatzTV.Core/Metadata/TelevisionFolderScanner.cs @@ -322,7 +322,7 @@ namespace ErsatzTV.Core.Metadata async () => { bool shouldUpdate = Optional(episode.EpisodeMetadata).Flatten().HeadOrNone().Match( - m => m.DateUpdated == DateTime.MinValue, + m => m.DateUpdated == SystemTime.MinValueUtc, true); if (shouldUpdate) diff --git a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs index 11b2226a5..5b7f174cd 100644 --- a/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs +++ b/ErsatzTV.Core/Scheduling/PlayoutBuilder.cs @@ -374,9 +374,9 @@ namespace ErsatzTV.Core.Scheduling } bool willNotFinishInTime = - currentTime <= durationFinish.IfNone(DateTime.MinValue) && + currentTime <= durationFinish.IfNone(SystemTime.MinValueUtc) && currentTime + peekVersion.Duration > - durationFinish.IfNone(DateTime.MinValue); + durationFinish.IfNone(SystemTime.MinValueUtc); if (willNotFinishInTime) { _logger.LogDebug( diff --git a/ErsatzTV.Core/SystemTime.cs b/ErsatzTV.Core/SystemTime.cs new file mode 100644 index 000000000..fc8dddbaf --- /dev/null +++ b/ErsatzTV.Core/SystemTime.cs @@ -0,0 +1,9 @@ +using System; + +namespace ErsatzTV.Core +{ + public static class SystemTime + { + public static DateTime MinValueUtc = new(0, DateTimeKind.Utc); + } +} diff --git a/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs b/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs index a46512c44..aba7bcfef 100644 --- a/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs +++ b/ErsatzTV.Infrastructure/Data/Repositories/TelevisionRepository.cs @@ -703,7 +703,7 @@ namespace ErsatzTV.Infrastructure.Data.Repositories new() { DateAdded = DateTime.UtcNow, - DateUpdated = DateTime.MinValue, + DateUpdated = SystemTime.MinValueUtc, MetadataKind = MetadataKind.Fallback, Actors = new List(), Guids = new List(), diff --git a/ErsatzTV.Infrastructure/Search/CustomQueryParser.cs b/ErsatzTV.Infrastructure/Search/CustomQueryParser.cs index c6fbbe91c..6ed89e6ca 100644 --- a/ErsatzTV.Infrastructure/Search/CustomQueryParser.cs +++ b/ErsatzTV.Infrastructure/Search/CustomQueryParser.cs @@ -1,4 +1,5 @@ using System; +using ErsatzTV.Core; using Lucene.Net.Analysis; using Lucene.Net.QueryParsers.Classic; using Lucene.Net.Search; @@ -53,7 +54,7 @@ namespace ErsatzTV.Infrastructure.Search internal static bool ParseStart(string text, out DateTime start) { - start = DateTime.MinValue; + start = SystemTime.MinValueUtc; try {