using System.Collections.ObjectModel; using System.Globalization; using System.Text; namespace View_by_Distance.Shared.Models.Stateless; internal abstract class XDate { internal static (int Season, string seasonName) GetSeason(int dayOfYear) { (int Season, string seasonName) result = dayOfYear switch { < 78 => new(0, "Winter"), < 124 => new(1, "Spring"), < 171 => new(2, "Spring"), < 217 => new(3, "Summer"), < 264 => new(4, "Summer"), < 309 => new(5, "Fall"), < 354 => new(6, "Fall"), _ => new(7, "Winter") }; return result; } private static (bool?, string[]) IsWrongYear(string[] segments, string year) { bool? result; string[] results = ( from l in segments where l?.Length > 2 && ( l[..2] is "18" or "19" or "20" || (l.Length == 5 && l.Substring(1, 2) is "18" or "19" or "20" && (l[0] is '~' or '=' or '-' or '^' or '#')) || (l.Length == 6 && l[..2] is "18" or "19" or "20" && l[4] == '.') || (l.Length == 7 && l.Substring(1, 2) is "18" or "19" or "20" && l[5] == '.') ) select l ).ToArray(); string[] matches = ( from l in results where l == year || (l.Length == 5 && l.Substring(1, 4) == year && (l[0] is '~' or '=' or '-' or '^' or '#')) || (l.Length == 6 && l[..4] == year && l[4] == '.') || (l.Length == 7 && l.Substring(1, 4) == year && l[5] == '.') select l ).ToArray(); if (results.Length == 0) result = null; else result = matches.Length == 0; return new(result, results); } internal static (bool?, string[]) IsWrongYear(FilePath filePath, ExifDirectory exifDirectory) { string[] results = []; bool? result = null; string year; string directoryName; string[] directorySegments; List collection = []; string? check = Path.GetFullPath(filePath.FullName); string? pathRoot = Path.GetPathRoot(filePath.FullName); if (string.IsNullOrEmpty(pathRoot)) throw new Exception(); DateTime? dateTimeOriginal = GetDateTimeOriginal(exifDirectory); if (dateTimeOriginal is not null) collection.Add(dateTimeOriginal.Value); else { ReadOnlyCollection dateTimes = GetDateTimes(exifDirectory); foreach (DateTime dateTime in dateTimes) collection.Add(dateTime); } foreach (DateTime dateTime in collection) { year = dateTime.ToString("yyyy"); for (int i = 0; i < int.MaxValue; i++) { check = Path.GetDirectoryName(check); if (string.IsNullOrEmpty(check) || check == pathRoot) break; directoryName = Path.GetFileName(check); directorySegments = directoryName.Split(' '); (result, results) = IsWrongYear(directorySegments, year); if (result is not null) break; } if (result is not null && !result.Value) break; } return new(result, results); } internal static DateTime? GetDateTimeOriginal(ExifDirectory exifDirectory) { DateTime? result; List results = []; foreach (ExifDirectoryBase exifDirectoryBase in exifDirectory.ExifBaseDirectories) { if (exifDirectoryBase.DateTimeOriginal is not null) results.Add(exifDirectoryBase.DateTimeOriginal.Value); } foreach (AviDirectory aviDirectory in exifDirectory.AviDirectories) { if (aviDirectory.DateTimeOriginal is not null) results.Add(aviDirectory.DateTimeOriginal.Value); } foreach (QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory in exifDirectory.QuickTimeMovieHeaderDirectories) { if (quickTimeMovieHeaderDirectory.Created is not null) { if (quickTimeMovieHeaderDirectory.Created.Value.Year == 1904 && quickTimeMovieHeaderDirectory.Created.Value.Month == 1 && quickTimeMovieHeaderDirectory.Created.Value.Day == 1) continue; results.Add(quickTimeMovieHeaderDirectory.Created.Value); } } foreach (QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory in exifDirectory.QuickTimeTrackHeaderDirectories) { if (quickTimeTrackHeaderDirectory.Created is not null) { if ((quickTimeTrackHeaderDirectory.Created.Value.Year is 1904 or 1970) && quickTimeTrackHeaderDirectory.Created.Value.Month == 1 && quickTimeTrackHeaderDirectory.Created.Value.Day == 1) continue; results.Add(quickTimeTrackHeaderDirectory.Created.Value); } } result = results.Count == 0 ? null : results.Min(); return result; } private static DateTime? GetDateTimeFromName(string fileNameWithoutExtension) { DateTime? result = null; int length; string format; string fullFormat; StringBuilder value = new(); const string ticksExample = "##################"; string[][] dateFormats = [ [string.Empty, "yyyyMMdd_HHmmss", string.Empty], [string.Empty, "yyyyMMddHHmmssfff", string.Empty], [string.Empty, "yyyyMMdd_", ticksExample], [string.Empty, "yyyy-MM-dd_", ticksExample], [string.Empty, "yyyy-MM-dd.", ticksExample], // [string.Empty, "yyyy-MM-dd.", $"{ticksExample}.{fileHolder.Length}"], [string.Empty, "yyyy-MM-dd HH.mm.ss", string.Empty], [string.Empty, "yyyyMMdd_HHmmss", "_LLS"], [string.Empty, "yyyyMMdd_HHmmss", "_HDR"], ["WIN_", "yyyyMMdd_HH_mm_ss", "_Pro"], ["IMG_", "yyyyMMdd_HHmmss", string.Empty], ["IMG#####-", "yyyyMMdd-HHmm", string.Empty], ["CameraZOOM-", "yyyyMMddHHmmss", string.Empty], ["VideoCapture_", "yyyyMMdd-HHmmss ", string.Empty] ]; foreach (string[] dateFormat in dateFormats) { _ = value.Clear(); if (dateFormat.Length != 3) throw new Exception(); fullFormat = string.Join(string.Empty, dateFormat); if (fileNameWithoutExtension.Length != fullFormat.Length) continue; format = dateFormat[1]; length = dateFormat[0].Length + dateFormat[1].Length; for (int i = dateFormat[0].Length; i < length; i++) _ = value.Append(fileNameWithoutExtension[i]); if (value.Length != format.Length) continue; if (DateTime.TryParseExact(value.ToString(), format, CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime checkDateTime)) { if (fileNameWithoutExtension.Length < ticksExample.Length || !long.TryParse(fileNameWithoutExtension[^ticksExample.Length..], out long ticks)) result = checkDateTime; else result = new DateTime(ticks); break; } } return result; } private static ReadOnlyCollection GetDateTimes(ExifDirectory exifDirectory) { List results = []; foreach (ExifDirectoryBase exifDirectoryBase in exifDirectory.ExifBaseDirectories) { if (exifDirectoryBase.DateTimeOriginal is not null) results.Add(exifDirectoryBase.DateTimeOriginal.Value); } foreach (AviDirectory aviDirectory in exifDirectory.AviDirectories) { if (aviDirectory.DateTimeOriginal is not null) results.Add(aviDirectory.DateTimeOriginal.Value); } foreach (QuickTimeMovieHeaderDirectory quickTimeMovieHeaderDirectory in exifDirectory.QuickTimeMovieHeaderDirectories) { if (quickTimeMovieHeaderDirectory.Created is not null) { if (quickTimeMovieHeaderDirectory.Created.Value.Year == 1904 && quickTimeMovieHeaderDirectory.Created.Value.Month == 1 && quickTimeMovieHeaderDirectory.Created.Value.Day == 1) continue; results.Add(quickTimeMovieHeaderDirectory.Created.Value); } } foreach (QuickTimeTrackHeaderDirectory quickTimeTrackHeaderDirectory in exifDirectory.QuickTimeTrackHeaderDirectories) { if (quickTimeTrackHeaderDirectory.Created is not null) { if ((quickTimeTrackHeaderDirectory.Created.Value.Year is 1904 or 1970) && quickTimeTrackHeaderDirectory.Created.Value.Month == 1 && quickTimeTrackHeaderDirectory.Created.Value.Day == 1) continue; results.Add(quickTimeTrackHeaderDirectory.Created.Value); } } if (results.Count == 0) { string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(exifDirectory.OriginalFileName); DateTime? dateTime = GetDateTimeFromName(fileNameWithoutExtension); if (dateTime is not null) results.Add(dateTime.Value); foreach (ExifDirectoryBase exifDirectoryBase in exifDirectory.ExifBaseDirectories) { if (exifDirectoryBase.DateTime is not null) results.Add(exifDirectoryBase.DateTime.Value); if (exifDirectoryBase.DateTimeDigitized is not null) results.Add(exifDirectoryBase.DateTimeDigitized.Value); } } if (results.Count == 0) { foreach (FileMetadataDirectory fileMetadataDirectory in exifDirectory.FileMetadataDirectories) { if (fileMetadataDirectory.FileModifiedDate is not null) results.Add(fileMetadataDirectory.FileModifiedDate.Value); } } return new(results); } internal static DateTime GetMinimum(ExifDirectory exifDirectory) { DateTime result; ReadOnlyCollection results = GetDateTimes(exifDirectory); result = results.Count == 0 ? DateTime.MinValue : results.Min(); return result; } }