Skip to content

Commit

Permalink
Add XmpDateTime::set_local_time_zone
Browse files Browse the repository at this point in the history
  • Loading branch information
scouten-adobe committed Nov 5, 2022
1 parent 1c3d03d commit 4490e89
Show file tree
Hide file tree
Showing 4 changed files with 149 additions and 0 deletions.
16 changes: 16 additions & 0 deletions src/ffi.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1369,6 +1369,22 @@ extern "C" {
#endif
}

void CXmpDateTimeSetTimeZone(XMP_DateTime* dt, CXmpError* outError) {
#ifndef NOOP_FFI
try {
if (dt) {
SXMPUtils::SetTimeZone(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 @@ -547,6 +547,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 CXmpDateTimeToString(
dt: *const CXmpDateTime,
out_error: *mut CXmpError,
Expand Down
73 changes: 73 additions & 0 deletions src/tests/xmp_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,79 @@ fn current() {
assert!(date.day <= 31);
}

mod set_local_time_zone {
use crate::{XmpDate, XmpDateTime, XmpError, XmpErrorType, 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.set_local_time_zone().unwrap();

// We don't know when writing this test what time zone will be used
// when running this test. All we can do is verify that *some* time zone
// was added and that other fields weren't altered. Print the result so
// it can be manually inspected.

println!("Manually verify correct local time zone: {:#?}", dt);

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_some());
}

#[test]
fn error_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 }),
}),
};

assert_eq!(
dt.set_local_time_zone().unwrap_err(),
XmpError {
error_type: XmpErrorType::BadParam,
debug_message: "SetTimeZone can only be used on zone-less times".to_owned()
}
);
}
}

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

Expand Down
58 changes: 58 additions & 0 deletions src/xmp_date_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,29 @@ impl XmpDateTime {
Ok(Self::from_ffi(&dt))
}

/// Sets the time zone to the local time zone.
///
/// Can only be used when there is a time with no existing time zone
/// (i.e. `self.time.time_zone.is_none()`). It is an error to call this
/// function with an existing time zone.
///
/// In that case, the time zone value is replaced with the local time zone.
/// The other date/time fields are
/// not adjusted in any way.
pub fn set_local_time_zone(&mut self) -> XmpResult<()> {
let mut dt = self.as_ffi();
let mut err = ffi::CXmpError::default();

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

XmpError::raise_from_c(&err)?;

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

pub(crate) fn from_ffi(dt: &ffi::CXmpDateTime) -> Self {
Self {
date: if dt.has_date {
Expand Down Expand Up @@ -133,6 +156,41 @@ impl XmpDateTime {
}
}

pub(crate) fn update_from_ffi(&mut self, dt: &ffi::CXmpDateTime) {
self.date = if dt.has_date {
Some(XmpDate {
year: dt.year,
month: dt.month,
day: dt.day,
})
} else {
None
};

self.time = if dt.has_time {
Some(XmpTime {
hour: dt.hour,
minute: dt.minute,
second: dt.second,
nanosecond: dt.nanosecond,
time_zone: if dt.has_time_zone {
Some(XmpTimeZone {
hour: if dt.tz_sign < 0 {
-dt.tz_hour
} else {
dt.tz_hour
},
minute: dt.tz_minute,
})
} else {
None
},
})
} else {
None
};
}

pub(crate) fn as_ffi(&self) -> ffi::CXmpDateTime {
let mut result = ffi::CXmpDateTime::default();

Expand Down

0 comments on commit 4490e89

Please sign in to comment.