Skip to content

Commit

Permalink
Add XmpDateTime::convert_to_local_time and `XmpDateTime::convert_to…
Browse files Browse the repository at this point in the history
…_utc`
  • Loading branch information
scouten-adobe committed Nov 5, 2022
1 parent c1b1c30 commit 5c76007
Show file tree
Hide file tree
Showing 4 changed files with 253 additions and 0 deletions.
32 changes: 32 additions & 0 deletions src/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,38 @@ extern "C" {
#endif
}

void CXmpDateTimeConvertToLocalTime(XMP_DateTime* dt, CXmpError* outError) {
#ifndef NOOP_FFI
try {
if (dt) {
SXMPUtils::ConvertToLocalTime(dt);
}
}
catch (XMP_Error& e) {
copyErrorForResult(e, outError);
}
catch (...) {
signalUnknownError(outError);
}
#endif
}

void CXmpDateTimeConvertToUTCTime(XMP_DateTime* dt, CXmpError* outError) {
#ifndef NOOP_FFI
try {
if (dt) {
SXMPUtils::ConvertToUTCTime(dt);
}
}
catch (XMP_Error& e) {
copyErrorForResult(e, outError);
}
catch (...) {
signalUnknownError(outError);
}
#endif
}

const char* CXmpDateTimeToString(const XMP_DateTime* dt, CXmpError* outError) {
#ifndef NOOP_FFI
try {
Expand Down
2 changes: 2 additions & 0 deletions src/ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -548,6 +548,8 @@ extern "C" {
pub(crate) fn CXmpDateTimeCurrent(dt: *mut CXmpDateTime, out_error: *mut CXmpError);

pub(crate) fn CXmpDateTimeSetTimeZone(dt: *mut CXmpDateTime, out_error: *mut CXmpError);
pub(crate) fn CXmpDateTimeConvertToLocalTime(dt: *mut CXmpDateTime, out_error: *mut CXmpError);
pub(crate) fn CXmpDateTimeConvertToUTCTime(dt: *mut CXmpDateTime, out_error: *mut CXmpError);

pub(crate) fn CXmpDateTimeToString(
dt: *const CXmpDateTime,
Expand Down
181 changes: 181 additions & 0 deletions src/tests/xmp_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,6 +121,187 @@ mod set_local_time_zone {
}
}

mod convert_to_local_time {
use crate::{XmpDate, XmpDateTime, XmpTime, XmpTimeZone};

#[test]
fn no_existing_tz() {
let mut dt = XmpDateTime {
date: Some(XmpDate {
year: 2022,
month: 11,
day: 5,
}),
time: Some(XmpTime {
hour: 14,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: None,
}),
};

dt.convert_to_local_time().unwrap();

assert_eq!(
dt.date.unwrap(),
XmpDate {
year: 2022,
month: 11,
day: 5
}
);

let time = dt.time.unwrap();
assert_eq!(time.hour, 14);
assert_eq!(time.minute, 40);
assert_eq!(time.second, 35);
assert_eq!(time.nanosecond, 42);
assert!(time.time_zone.is_none());
}

#[test]
fn existing_tz() {
let mut dt = XmpDateTime {
date: Some(XmpDate {
year: 2022,
month: 11,
day: 5,
}),
time: Some(XmpTime {
hour: 14,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: Some(XmpTimeZone { hour: 1, minute: 2 }),
// Use an unusual time zone so we can determine if
// *something* changed.
}),
};

dt.convert_to_local_time().unwrap();

// Since we don't know when writing this test what time
// zone will be in effect when running this test, we do some
// basic sanity checks to ensure that *something* changed.

println!("Updated date time = {:#?}", dt);

assert_eq!(dt.date.unwrap().year, 2022);

let time = dt.time.unwrap();

assert_ne!(
time,
XmpTime {
hour: 14,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: Some(XmpTimeZone { hour: 1, minute: 2 }),
}
);

assert_ne!(time.minute, 40);
}
}

mod convert_to_utc {
use crate::{XmpDate, XmpDateTime, XmpTime, XmpTimeZone};

#[test]
fn no_existing_tz() {
let original_dt = XmpDateTime {
date: Some(XmpDate {
year: 2022,
month: 11,
day: 5,
}),
time: Some(XmpTime {
hour: 14,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: None,
}),
};

let mut dt = original_dt.clone();
dt.convert_to_utc().unwrap();

assert_eq!(original_dt, dt);
}

#[test]
fn existing_tz() {
let mut dt = XmpDateTime {
date: Some(XmpDate {
year: 2022,
month: 11,
day: 5,
}),
time: Some(XmpTime {
hour: 19,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: Some(XmpTimeZone {
hour: -7,
minute: 0,
}),
}),
};

dt.convert_to_utc().unwrap();

println!("Updated date time = {:#?}", dt);

assert_eq!(
dt,
XmpDateTime {
date: Some(XmpDate {
year: 2022,
month: 11,
day: 6,
}),
time: Some(XmpTime {
hour: 2,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: Some(XmpTimeZone { hour: 0, minute: 0 }),
}),
}
);
}

#[test]
fn already_utc() {
let original_dt = XmpDateTime {
date: Some(XmpDate {
year: 2022,
month: 11,
day: 5,
}),
time: Some(XmpTime {
hour: 19,
minute: 40,
second: 35,
nanosecond: 42,
time_zone: Some(XmpTimeZone { hour: 0, minute: 0 }),
}),
};

let mut dt = original_dt.clone();

dt.convert_to_utc().unwrap();

println!("Updated date time = {:#?}", dt);

assert_eq!(original_dt, dt);
}
}

mod from_ffi {
use crate::{ffi, XmpDate, XmpDateTime, XmpTime, XmpTimeZone};

Expand Down
38 changes: 38 additions & 0 deletions src/xmp_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,44 @@ impl XmpDateTime {
Ok(())
}

/// Translate the value to the local time zone.
///
/// If the time zone is not the local zone, the time is adjusted and the
/// time zone set to be local. The value is not modified if the time zone is
/// already the local zone or if the value has no time zone.
pub fn convert_to_local_time(&mut self) -> XmpResult<()> {
let mut dt = self.as_ffi();
let mut err = ffi::CXmpError::default();

unsafe {
ffi::CXmpDateTimeConvertToLocalTime(&mut dt, &mut err);
}

XmpError::raise_from_c(&err)?;

self.update_from_ffi(&dt);
Ok(())
}

/// Translates the value to UTC (Coordinated Universal Time).
///
/// If the time zone is not UTC, the time is adjusted and the time zone set
/// to be UTC. The value is not modified if the time zone is already UTC or
/// if the value has no time zone.
pub fn convert_to_utc(&mut self) -> XmpResult<()> {
let mut dt = self.as_ffi();
let mut err = ffi::CXmpError::default();

unsafe {
ffi::CXmpDateTimeConvertToUTCTime(&mut dt, &mut err);
}

XmpError::raise_from_c(&err)?;

self.update_from_ffi(&dt);
Ok(())
}

pub(crate) fn from_ffi(dt: &ffi::CXmpDateTime) -> Self {
let mut result = Self::default();
result.update_from_ffi(dt);
Expand Down

0 comments on commit 5c76007

Please sign in to comment.