baseunits_rs/time/
calendar_date.rs

1use chrono::{Date, Datelike, DateTime, TimeZone, Utc};
2use num::FromPrimitive;
3use time::Duration as OldDuration;
4
5use crate::time::{CalendarYearMonth, DayOfMonth, DayOfWeek, TimePoint};
6use std::ops::{Sub, Add};
7
8#[derive(Debug, Clone, Eq, PartialEq, PartialOrd, Hash)]
9pub struct CalendarDate {
10  year_month: CalendarYearMonth,
11  day: DayOfMonth,
12}
13
14impl ToString for CalendarDate {
15  fn to_string(&self) -> String {
16    unimplemented!()
17  }
18}
19
20impl<T> From<Date<T>> for CalendarDate
21where
22  T: TimeZone,
23{
24  fn from(value: Date<T>) -> Self {
25    let dt: DateTime<T> = value.and_hms_milli(0, 0, 0, 0);
26    Self::from(dt)
27  }
28}
29
30impl<T> From<DateTime<T>> for CalendarDate
31where
32  T: TimeZone,
33{
34  fn from(value: DateTime<T>) -> Self {
35    let cym = CalendarYearMonth::from((value.year(), value.month()));
36    let dom = DayOfMonth::new(value.day());
37    CalendarDate::new(cym, dom)
38  }
39}
40
41impl From<TimePoint> for CalendarDate {
42  fn from(time_point: TimePoint) -> Self {
43    Self::from((time_point, Utc))
44  }
45}
46
47impl<T: TimeZone> From<(TimePoint, T)> for CalendarDate {
48  fn from((time_point, time_zone): (TimePoint, T)) -> Self {
49    let date_time = time_point.to_date_time(time_zone);
50    let cym = CalendarYearMonth::from((date_time.year(), date_time.month()));
51    let dom = DayOfMonth::new(date_time.day());
52    CalendarDate::new(cym, dom)
53  }
54}
55
56impl From<(CalendarYearMonth, DayOfMonth)> for CalendarDate {
57  fn from((year_month, day): (CalendarYearMonth, DayOfMonth)) -> Self {
58    Self::new(year_month, day)
59  }
60}
61
62impl From<(i32, u32, u32)> for CalendarDate {
63  fn from((year, month, day): (i32, u32, u32)) -> Self {
64    let cym = CalendarYearMonth::from((year, month));
65    let dom = DayOfMonth::new(day);
66    Self::new(cym, dom)
67  }
68}
69
70impl CalendarDate {
71  /// コンストラクタ
72  pub fn new(year_month: CalendarYearMonth, day: DayOfMonth) -> Self {
73    Self { year_month, day }
74  }
75
76  pub fn as_year_month(&self) -> &CalendarYearMonth {
77    &self.year_month
78  }
79
80  pub fn to_year_month(&self) -> CalendarYearMonth {
81    self.year_month.clone()
82  }
83
84  pub fn as_day(&self) -> &DayOfMonth {
85    &self.day
86  }
87
88  pub fn to_day(&self) -> DayOfMonth {
89    self.day.clone()
90  }
91
92  pub fn to_date_time_on_midnight_at_utc(&self) -> DateTime<Utc> {
93    self.to_date_time_on_midnight(Utc)
94  }
95
96  pub fn to_date_time_on_midnight<T: TimeZone>(&self, time_zone: T) -> DateTime<T> {
97    time_zone
98      .ymd(
99        self.year_month.to_year(),
100        self.year_month.to_month_u32(),
101        self.day.0,
102      )
103      .and_hms_milli(0, 0, 0, 0)
104  }
105
106  pub fn day_of_week_at_utc(&self) -> DayOfWeek {
107    self.day_of_week(Utc)
108  }
109
110  pub fn day_of_week<T: TimeZone>(&self, time_zone: T) -> DayOfWeek {
111    let no = self
112      .to_date_time_on_midnight(time_zone)
113      .date()
114      .weekday()
115      .number_from_monday();
116    DayOfWeek::from_u32(no).unwrap()
117  }
118
119  pub fn add_days<T>(&self, days: i64, time_zone: T) -> Self
120  where
121    T: TimeZone,
122  {
123    let date_time = self.to_date_time_on_midnight(time_zone);
124    let new_date_time = date_time.add(OldDuration::days(days));
125    Self::from(new_date_time)
126  }
127
128  pub fn subtract_days<T>(&self, days: i64, time_zone: T) -> Self
129  where
130    T: TimeZone,
131  {
132    let date_time = self.to_date_time_on_midnight(time_zone);
133    let new_date_time = date_time.sub(OldDuration::days(days));
134    Self::from(new_date_time)
135  }
136
137  pub fn subtract_months<T>(&self, months: i64, time_zone: T) -> Self
138  where
139    T: TimeZone,
140  {
141    let date_time = self.to_date_time_on_midnight(time_zone);
142    let new_date_time = date_time - OldDuration::days(30 * months);
143    Self::from(new_date_time)
144  }
145
146  pub fn add_months<T>(&self, months: i64, time_zone: T) -> Self
147  where
148    T: TimeZone,
149  {
150    let date_time = self.to_date_time_on_midnight(time_zone);
151    let new_date_time = date_time + OldDuration::days(30 * months);
152    Self::from(new_date_time)
153  }
154
155  pub fn is_after(&self, other: &Self) -> bool {
156    !self.is_before(other) && self != other
157  }
158
159  pub fn is_before(&self, other: &Self) -> bool {
160    if self.year_month.is_before(&other.year_month) {
161      true
162    } else if self.year_month.is_after(&other.year_month) {
163      false
164    } else {
165      self.day.is_before(&other.day)
166    }
167  }
168}