diff --git a/lib/model/video/metadata.dart b/lib/model/video/metadata.dart index e5e7f1a00..ef90fb267 100644 --- a/lib/model/video/metadata.dart +++ b/lib/model/video/metadata.dart @@ -23,7 +23,7 @@ import 'package:flutter/foundation.dart'; class VideoMetadataFormatter { static final _dateY4M2D2H2m2s2Pattern = RegExp(r'(\d{4})[-/](\d{2})[-/](\d{2}) (\d{2}):(\d{2}):(\d{2})'); - static final _dateY4M2D2H2m2s2APmPattern = RegExp(r'(\d{4})[-/](\d{2})[-/](\d{2})T(\d+):(\d+):(\d+) ([ap]m)Z'); + static final _dateY4M2D2H2m2s2APmPattern = RegExp(r'(\d{4})[-/](\d{1,2})[-/](\d{1,2})T(\d+):(\d+):(\d+)( ([ap]m))?Z'); static final _ambiguousDatePatterns = { RegExp(r'^\d{2}[-/]\d{2}[-/]\d{4}$'), }; @@ -124,6 +124,7 @@ class VideoMetadataFormatter { // - `UTC 2021-05-30 19:14:21` // - `2021/10/31 21:23:17` // - `2021-09-10T7:14:49 pmZ` + // - `2012-1-1T12:00:00Z` // - `2021` (not enough to build a date) var match = _dateY4M2D2H2m2s2Pattern.firstMatch(dateString); @@ -149,7 +150,7 @@ class VideoMetadataFormatter { final hour = int.tryParse(match.group(4)!); final minute = int.tryParse(match.group(5)!); final second = int.tryParse(match.group(6)!); - final pm = match.group(7) == 'pm'; + final pm = match.group(8) == 'pm'; if (year != null && month != null && day != null && hour != null && minute != null && second != null) { final date = DateTime(year, month, day, hour + (pm ? 12 : 0), minute, second, 0); diff --git a/lib/utils/time_utils.dart b/lib/utils/time_utils.dart index 1c28bae55..c6d4dd563 100644 --- a/lib/utils/time_utils.dart +++ b/lib/utils/time_utils.dart @@ -47,7 +47,8 @@ DateTime? dateTimeFromMillis(int? millis, {bool isUtc = false}) { final _unixStampMillisPattern = RegExp(r'\d{13}'); final _unixStampSecPattern = RegExp(r'\d{10}'); -final _plainPattern = RegExp(r'(\d{8})([_-\s](\d{6})([_-\s](\d{3}))?)?'); +final _dateYMD8Hms6Sub3Pattern = RegExp(r'(\d{8})([_-\s](\d{6})([_-\s](\d{3}))?)?'); +final _dateY4M2D2H2m2s2Sub3Pattern = RegExp(r'(\d{4})-(\d{1,2})-(\d{1,2})-(\d{1,2})-(\d{1,2})-(\d{1,2})-(\d{1,3})'); DateTime? parseUnknownDateFormat(String? s) { if (s == null) return null; @@ -74,7 +75,7 @@ DateTime? parseUnknownDateFormat(String? s) { } } - match = _plainPattern.firstMatch(s); + match = _dateYMD8Hms6Sub3Pattern.firstMatch(s); if (match != null) { final dateString = match.group(1); final timeString = match.group(3); @@ -101,5 +102,20 @@ DateTime? parseUnknownDateFormat(String? s) { } } + match = _dateY4M2D2H2m2s2Sub3Pattern.firstMatch(s); + if (match != null) { + final year = int.tryParse(match.group(1)!); + final month = int.tryParse(match.group(2)!); + final day = int.tryParse(match.group(3)!); + final hour = int.tryParse(match.group(4)!); + final minute = int.tryParse(match.group(5)!); + final second = int.tryParse(match.group(6)!); + final millis = int.tryParse(match.group(7)!); + + if (year != null && month != null && day != null && hour != null && minute != null && second != null && millis != null) { + return DateTime(year, month, day, hour, minute, second, millis); + } + } + return null; } diff --git a/test/model/video/metadata_test.dart b/test/model/video/metadata_test.dart index b3b3a3c13..dd009e43c 100644 --- a/test/model/video/metadata_test.dart +++ b/test/model/video/metadata_test.dart @@ -9,6 +9,7 @@ void main() { expect(VideoMetadataFormatter.parseVideoDate('UTC 2021-05-30 19:14:21'), DateTime(2021, 5, 30, 19, 14, 21).millisecondsSinceEpoch); expect(VideoMetadataFormatter.parseVideoDate('2021/10/31 21:23:17'), DateTime(2021, 10, 31, 21, 23, 17).millisecondsSinceEpoch); expect(VideoMetadataFormatter.parseVideoDate('2021-09-10T7:14:49 pmZ'), DateTime(2021, 9, 10, 19, 14, 49).millisecondsSinceEpoch); + expect(VideoMetadataFormatter.parseVideoDate('2012-1-1T12:00:00Z'), DateTime(2012, 1, 1, 12, 0, 0).millisecondsSinceEpoch); }); test('Ambiguous date', () { diff --git a/test/utils/time_utils_test.dart b/test/utils/time_utils_test.dart index 1e5cefb69..b6c49cdef 100644 --- a/test/utils/time_utils_test.dart +++ b/test/utils/time_utils_test.dart @@ -19,13 +19,15 @@ void main() { test('Parse dates', () { final localOffset = DateTime.now().timeZoneOffset; - expect(parseUnknownDateFormat('1600995564713'), DateTime(2020, 09, 25, 0, 59, 24, 713).add(localOffset)); - expect(parseUnknownDateFormat('pre1600995564713suf'), DateTime(2020, 09, 25, 0, 59, 24, 713).add(localOffset)); + expect(parseUnknownDateFormat('1600995564713'), DateTime(2020, 9, 25, 0, 59, 24, 713).add(localOffset)); + expect(parseUnknownDateFormat('pre1600995564713suf'), DateTime(2020, 9, 25, 0, 59, 24, 713).add(localOffset)); - expect(parseUnknownDateFormat('1600995564'), DateTime(2020, 09, 25, 0, 59, 24, 0).add(localOffset)); - expect(parseUnknownDateFormat('pre1600995564suf'), DateTime(2020, 09, 25, 0, 59, 24, 0).add(localOffset)); + expect(parseUnknownDateFormat('1600995564'), DateTime(2020, 9, 25, 0, 59, 24, 0).add(localOffset)); + expect(parseUnknownDateFormat('pre1600995564suf'), DateTime(2020, 9, 25, 0, 59, 24, 0).add(localOffset)); - expect(parseUnknownDateFormat('IMG_20210901_142523_783'), DateTime(2021, 09, 1, 14, 25, 23, 783)); + expect(parseUnknownDateFormat('IMG_20210901_142523_783'), DateTime(2021, 9, 1, 14, 25, 23, 783)); expect(parseUnknownDateFormat('Screenshot_20211028-115056_Aves'), DateTime(2021, 10, 28, 11, 50, 56, 0)); + + expect(parseUnknownDateFormat('Screenshot_2022-05-14-15-40-29-164_uri'), DateTime(2022, 5, 14, 15, 40, 29, 164)); }); }