1use async_trait::async_trait;
2use chrono::{DateTime, Duration, TimeZone, Utc};
3use crate::bytes_read::{Mp4VersionedReadable, ReadMp4};
4use crate::bytes_write::{FlagTrait, Mp4VersionedWritable, WriteMp4};
5use crate::error::MP4Error;
6use crate::types::versioned_u32_u64::VersionedU32U64;
7
8pub fn base_date() -> DateTime<Utc> {
9 Utc.ymd(1904, 1, 1).and_hms(0, 0, 0)
10}
11
12#[derive(Copy, Clone, Debug, Ord, PartialOrd, Eq, PartialEq, Hash)]
13pub struct Mp4DateTime(VersionedU32U64);
14
15impl Default for Mp4DateTime {
16 fn default() -> Self {
17 Utc::now().into()
18 }
19}
20
21
22impl From<DateTime<Utc>> for Mp4DateTime {
23 fn from(date: DateTime<Utc>) -> Self {
24 Self(VersionedU32U64(date.signed_duration_since(base_date()).num_seconds() as u64))
25 }
26}
27
28impl From<Mp4DateTime> for DateTime<Utc> {
29 fn from(date: Mp4DateTime) -> Self {
30 base_date() + Duration::seconds(date.0.0 as i64)
31 }
32}
33
34#[async_trait]
35impl<F: FlagTrait> Mp4VersionedReadable<F> for Mp4DateTime {
36 async fn versioned_read<R: ReadMp4 + ?Sized>(version: u8, flags: F, reader: &mut R) -> Result<Self, MP4Error> {
37 Ok(Self(reader.versioned_read(version, flags).await?))
38 }
39}
40
41impl<F: FlagTrait> Mp4VersionedWritable<F> for Mp4DateTime {
42 fn required_version(&self) -> u8 {
43 <VersionedU32U64 as Mp4VersionedWritable<F>>::required_version(&self.0)
44 }
45
46 fn versioned_byte_size(&self, version: u8, flags: F) -> usize {
47 self.0.versioned_byte_size(version, flags)
48 }
49
50 fn versioned_write<W: WriteMp4>(&self, version: u8, flags: F, writer: &mut W) -> Result<usize, MP4Error> {
51 self.0.versioned_write(version, flags, writer)
52 }
53}