1 | /* |
2 | This file is part of the KFileMetaData project |
3 | SPDX-FileCopyrightText: 2024 Stefan BrĂ¼ns <stefan.bruens@rwth-aachen.de> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.1-or-later |
6 | */ |
7 | |
8 | #include "kfilemetadata_debug.h" |
9 | |
10 | #include <QDateTime> |
11 | #include <QString> |
12 | #include <QTimeZone> |
13 | |
14 | #include <array> |
15 | |
16 | namespace KFileMetaData |
17 | { |
18 | namespace Parser |
19 | { |
20 | |
21 | inline QDateTime dateTimeFromExifString(QStringView dateString, QStringView subSecsString, QStringView offsetString, std::optional<int> offsetSecs) |
22 | { |
23 | using namespace Qt::Literals::StringLiterals; |
24 | |
25 | if (auto dateTime = QDateTime::fromString(string: dateString, format: u"yyyy:MM:dd hh:mm:ss"_s ); dateTime.isValid()) { |
26 | subSecsString = subSecsString.trimmed(); |
27 | if (!subSecsString.isEmpty()) { |
28 | long subSecs = 0; |
29 | if (subSecsString.size() >= 4) { |
30 | subSecsString = subSecsString.first(n: 4); |
31 | subSecs = (subSecsString.toLong() + 5) / 10; |
32 | } else if (subSecsString.size() == 3) { |
33 | subSecs = subSecsString.toLong(); |
34 | } else if (subSecsString.size() == 2) { |
35 | subSecs = subSecsString.toLong() * 10; |
36 | } else if (subSecsString.size() == 1) { |
37 | subSecs = subSecsString.toLong() * 100; |
38 | } |
39 | dateTime = dateTime.addMSecs(msecs: subSecs); |
40 | } |
41 | if (!offsetString.isEmpty()) { |
42 | if (auto offset = QDateTime::fromString(string: offsetString, format: u"ttt"_s ); offset.isValid()) { |
43 | dateTime.setTimeZone(toZone: offset.timeZone()); |
44 | } else { |
45 | qCWarning(KFILEMETADATA_LOG) << "Could not parse timezone from:" << offsetString; |
46 | } |
47 | } else if (offsetSecs) { |
48 | dateTime.setTimeZone(toZone: QTimeZone(*offsetSecs)); |
49 | } |
50 | return dateTime; |
51 | } |
52 | |
53 | qCWarning(KFILEMETADATA_LOG) << "Could not parse datetime from:" << dateString << subSecsString << offsetString; |
54 | return {}; |
55 | } |
56 | |
57 | inline QDateTime dateTimeFromString(const QString &dateString) |
58 | { |
59 | if (auto dateTime = QDateTime::fromString(string: dateString, format: Qt::ISODate); dateTime.isValid()) { |
60 | return dateTime; |
61 | } |
62 | |
63 | std::array<QString, 13> formats{ |
64 | QStringLiteral("yyyy-MM-dd" ), |
65 | QStringLiteral("dd-MM-yyyy" ), |
66 | QStringLiteral("yyyy-MM" ), |
67 | QStringLiteral("MM-yyyy" ), |
68 | QStringLiteral("yyyy.MM.dd" ), |
69 | QStringLiteral("dd.MM.yyyy" ), |
70 | QStringLiteral("dd MMMM yyyy" ), |
71 | QStringLiteral("MM.yyyy" ), |
72 | QStringLiteral("yyyy.MM" ), |
73 | QStringLiteral("yyyy" ), |
74 | QStringLiteral("yy" ), |
75 | QStringLiteral("dddd d MMM yyyy h':'mm':'ss AP" ), |
76 | QStringLiteral("yyyy:MM:dd hh:mm:ss" ), |
77 | }; |
78 | |
79 | for (const auto& formatString : formats) { |
80 | if (auto dateTime = QDateTime::fromString(string: dateString, format: formatString); dateTime.isValid()) { |
81 | dateTime.setTimeZone(toZone: QTimeZone::UTC); |
82 | return dateTime; |
83 | } |
84 | } |
85 | |
86 | if (auto dateTime = QLocale().toDateTime(string: dateString, format: QLocale::ShortFormat); dateTime.isValid()) { |
87 | dateTime.setTimeZone(toZone: QTimeZone::UTC); |
88 | return dateTime; |
89 | } |
90 | |
91 | if (auto dateTime = QLocale().toDateTime(string: dateString, format: QLocale::LongFormat); dateTime.isValid()) { |
92 | dateTime.setTimeZone(toZone: QTimeZone::UTC); |
93 | return dateTime; |
94 | } |
95 | |
96 | qCWarning(KFILEMETADATA_LOG) << "Could not determine correct datetime format from:" << dateString; |
97 | return {}; |
98 | } |
99 | |
100 | } // namespace Parser |
101 | } // namespace KFileMetaData |
102 | |