use chrono::NaiveDateTime;
use std::io::{Read, Seek};
use std::str::FromStr;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum ExifDateType {
Modify,
Creation,
Digitized,
}
impl FromStr for ExifDateType {
type Err = anyhow::Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"modify" | "m" | "modified" => Ok(ExifDateType::Modify),
"creation" | "c" | "create" | "created" => Ok(ExifDateType::Creation),
"digitized" | "digitize" | "d" | "digital" | "digitalize" => {
Ok(ExifDateType::Digitized)
}
_ => Err(anyhow::anyhow!(
"Invalid EXIF date type: {s}. Possible values are modify/create/digitize"
)),
}
}
}
pub fn get_exif_time<R: Read + Seek>(
file: R,
date_type: ExifDateType,
) -> anyhow::Result<Option<NaiveDateTime>> {
let mut bufreader = std::io::BufReader::new(file);
let exifreader = exif::Reader::new();
let exif = exifreader.read_from_container(&mut bufreader)?;
let datetime = exif.get_field(
match date_type {
ExifDateType::Modify => exif::Tag::DateTime,
ExifDateType::Creation => exif::Tag::DateTimeOriginal,
ExifDateType::Digitized => exif::Tag::DateTimeDigitized,
},
exif::In::PRIMARY,
);
Ok(datetime
.map(|field| {
let datetime = field.display_value().to_string();
NaiveDateTime::parse_from_str(&datetime, "%Y-%m-%d %H:%M:%S")
})
.transpose()?)
}