1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// This file is part of ICU4X. For terms of use, please see the file
// called LICENSE at the top level of the ICU4X source tree
// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).

use crate::date::{LocalizedDateTimeInput, ZonedDateTimeInputWithLocale};
use crate::error::DateTimeFormatError as Error;
use crate::fields::{self, FieldSymbol};
use crate::pattern::PatternItem;
use crate::{date::ZonedDateTimeInput, zoned_datetime::ZonedDateTimeFormat};
use std::fmt;
use writeable::Writeable;

use super::datetime;
use super::time_zone;

pub struct FormattedZonedDateTime<'l, T>
where
    T: ZonedDateTimeInput,
{
    pub(crate) zoned_datetime_format: &'l ZonedDateTimeFormat<'l>,
    pub(crate) zoned_datetime: &'l T,
}

impl<'l, T> Writeable for FormattedZonedDateTime<'l, T>
where
    T: ZonedDateTimeInput,
{
    fn write_to<W: fmt::Write + ?Sized>(&self, sink: &mut W) -> fmt::Result {
        write_pattern(self.zoned_datetime_format, self.zoned_datetime, sink)
            .map_err(|_| std::fmt::Error)
    }

    // TODO(#489): Implement write_len
}

impl<'l, T> fmt::Display for FormattedZonedDateTime<'l, T>
where
    T: ZonedDateTimeInput,
{
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write_pattern(self.zoned_datetime_format, self.zoned_datetime, f)
            .map_err(|_| std::fmt::Error)
    }
}

pub fn write_pattern<T, W>(
    zoned_datetime_format: &ZonedDateTimeFormat,
    zoned_datetime: &T,
    w: &mut W,
) -> Result<(), Error>
where
    T: ZonedDateTimeInput,
    W: fmt::Write + ?Sized,
{
    let locale = &zoned_datetime_format.datetime_format.locale;
    let pattern = &zoned_datetime_format.datetime_format.pattern;
    let loc_datetime = ZonedDateTimeInputWithLocale::new(zoned_datetime, locale);
    for item in pattern.items() {
        match item {
            PatternItem::Field(field) => {
                write_field(field, zoned_datetime_format, &loc_datetime, w)?
            }
            PatternItem::Literal(l) => w.write_str(l)?,
        }
    }
    Ok(())
}

fn write_field<T, W>(
    field: &fields::Field,
    zoned_datetime_format: &ZonedDateTimeFormat,
    loc_datetime: &impl LocalizedDateTimeInput<T>,
    w: &mut W,
) -> Result<(), Error>
where
    T: ZonedDateTimeInput,
    W: fmt::Write + ?Sized,
{
    let pattern = &zoned_datetime_format.datetime_format.pattern;
    let symbols = &zoned_datetime_format.datetime_format.symbols;

    match field.symbol {
        FieldSymbol::TimeZone(_time_zone) => time_zone::write_field(
            field,
            &zoned_datetime_format.time_zone_format,
            loc_datetime.datetime(),
            w,
        )?,
        _ => datetime::write_field(pattern, field, symbols, loc_datetime, w)?,
    }
    Ok(())
}