Set creation date for images using EXIF

This commit is contained in:
Leon Böttger committed 2025-06-29 18:58:58 +02:00
1 parent 34d677fb92
commit 7403e70893
2 files changed
+55 -5

No files matched your search

+51 -1
View File
@@ -11,7 +11,7 @@ import CryptoKit
import Foundation
import Network
import System
import ImageIO
import BigInt
import SwiftECC
@@ -518,6 +518,9 @@ public class SaveFilesManager {
public func registerFileFinishedDownloading(_ fileURL: URL) {
filesFinishedDownloading.append(fileURL)
filesFinishedDownloadingSinceLastRun.append(fileURL)
// read out EXIF timestamp and manually set file creation date to it
applyEXIFTimestamps(at: fileURL)
}
public func movePendingFilesToTarget() {
@@ -633,6 +636,53 @@ public class SaveFilesManager {
fatalError("Failed to get downloads directory: \(error)")
}
}
/// Returns the EXIF original date of an image file, adjusted to the current time zone.
private func exifOriginalDate(from url: URL) -> Date? {
guard let imageSource = CGImageSourceCreateWithURL(url as CFURL, nil),
let properties = CGImageSourceCopyPropertiesAtIndex(imageSource, 0, nil) as? [CFString: Any],
let exif = properties[kCGImagePropertyExifDictionary] as? [CFString: Any],
let dateString = exif[kCGImagePropertyExifDateTimeOriginal] as? String
else {
return nil
}
let formatter = DateFormatter()
formatter.dateFormat = "yyyy:MM:dd HH:mm:ss"
formatter.timeZone = TimeZone.current // Use the current device time zone
return formatter.date(from: dateString)
}
/// Applies EXIF timestamps to a given file or directory.
private func applyEXIFTimestamps(at url: URL) {
let fm = FileManager.default
var isDir: ObjCBool = false
guard fm.fileExists(atPath: url.path, isDirectory: &isDir) else { return }
if isDir.boolValue {
// It's a directory — enumerate files
if let enumerator = fm.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey]) {
for case let fileURL as URL in enumerator {
guard (try? fileURL.resourceValues(forKeys: [.isRegularFileKey]))?.isRegularFile == true else { continue }
applyEXIFTimestamp(to: fileURL)
}
}
} else {
// It's a single file
applyEXIFTimestamp(to: url)
}
}
/// Applies EXIF timestamp (if available) to a single file
private func applyEXIFTimestamp(to fileURL: URL) {
guard let exifDate = exifOriginalDate(from: fileURL) else {
return
}
// Set the "creation date"
try? FileManager.default.setAttributes([.creationDate: exifDate], ofItemAtPath: fileURL.path)
}
}
extension Data {
+4 -4
View File
@@ -825,8 +825,8 @@
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
SHARED_BUILD = 46;
SHARED_VERSION = 1.9.4;
SHARED_BUILD = 47;
SHARED_VERSION = 1.10;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
};
@@ -884,8 +884,8 @@
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SHARED_BUILD = 46;
SHARED_VERSION = 1.9.4;
SHARED_BUILD = 47;
SHARED_VERSION = 1.10;
SWIFT_COMPILATION_MODE = wholemodule;
SWIFT_OPTIMIZATION_LEVEL = "-O";
};