Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
21 changes: 17 additions & 4 deletions crates/ui/src/time/calendar.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::{borrow::Cow, rc::Rc};

use chrono::{Datelike, Local, NaiveDate};
use chrono::{Datelike, Local, NaiveDate, Weekday};
use gpui::{
App, ClickEvent, Context, Div, ElementId, Empty, Entity, EventEmitter, FocusHandle,
InteractiveElement, IntoElement, ParentElement, Render, RenderOnce, SharedString, Stateful,
Expand Down Expand Up @@ -266,6 +266,8 @@ pub struct Calendar {
style: StyleRefinement,
/// Number of the months view to show.
number_of_months: usize,
/// The first day of the week. Defaults to Sunday.
first_day_of_week: Weekday,
}

/// Use to store the state of the calendar.
Expand Down Expand Up @@ -411,10 +413,14 @@ impl CalendarState {
}

/// Returns the days of the month in a 2D vector to render on calendar.
fn days(&self) -> Vec<Vec<NaiveDate>> {
fn days(&self, first_day: Weekday) -> Vec<Vec<NaiveDate>> {
(0..self.number_of_months)
.flat_map(|offset| {
days_in_month(self.current_year, self.current_month as u32 + offset as u32)
days_in_month(
self.current_year,
self.current_month as u32 + offset as u32,
first_day,
)
})
.collect()
}
Expand Down Expand Up @@ -539,6 +545,7 @@ impl Calendar {
state: state.clone(),
style: StyleRefinement::default(),
number_of_months: 1,
first_day_of_week: Weekday::Sun,
}
}

Expand All @@ -548,6 +555,12 @@ impl Calendar {
self
}

/// Set the first day of the week for the calendar.
pub fn first_day_of_week(mut self, day: Weekday) -> Self {
self.first_day_of_week = day;
self
}

fn render_day(
&self,
d: &NaiveDate,
Expand Down Expand Up @@ -803,7 +816,7 @@ impl Calendar {
.justify_between()
.children(
state
.days()
.days(self.first_day_of_week)
.chunks(5)
.enumerate()
.map(|(offset_month, days)| {
Expand Down
12 changes: 11 additions & 1 deletion crates/ui/src/time/date_picker.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use std::rc::Rc;

use chrono::NaiveDate;
use chrono::{NaiveDate, Weekday};
use gpui::{
App, AppContext, ClickEvent, Context, ElementId, Empty, Entity, EventEmitter, FocusHandle,
Focusable, InteractiveElement as _, IntoElement, KeyBinding, MouseButton, ParentElement as _,
Expand Down Expand Up @@ -77,6 +77,8 @@ pub struct DatePickerState {
number_of_months: usize,
disabled_matcher: Option<Rc<Matcher>>,
_subscriptions: Vec<Subscription>,
/// The first day of the week. Defaults to Sunday.
first_day_of_week: Weekday,
}

impl Focusable for DatePickerState {
Expand Down Expand Up @@ -130,6 +132,7 @@ impl DatePickerState {
number_of_months: 1,
disabled_matcher: None,
_subscriptions,
first_day_of_week: Weekday::Sun,
}
}

Expand All @@ -145,6 +148,12 @@ impl DatePickerState {
self
}

/// Set the first day of the week.
pub fn first_day_of_week(mut self, day: Weekday) -> Self {
self.first_day_of_week = day;
self
}

/// Get the date of the date picker.
pub fn date(&self) -> Date {
self.date
Expand Down Expand Up @@ -501,6 +510,7 @@ impl RenderOnce for DatePicker {
.child(
Calendar::new(&state.calendar)
.number_of_months(self.number_of_months)
.first_day_of_week(state.first_day_of_week)
.border_0()
.rounded_none()
.p_0()
Expand Down
11 changes: 6 additions & 5 deletions crates/ui/src/time/utils.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use chrono::{Datelike, Duration, NaiveDate};
use chrono::{Datelike, Duration, NaiveDate, Weekday};

trait NaiveDateExt {
fn days_in_month(&self) -> i32;
Expand Down Expand Up @@ -28,7 +28,7 @@ impl NaiveDateExt for chrono::NaiveDate {
}
}

pub(crate) fn days_in_month(year: i32, month: u32) -> Vec<Vec<NaiveDate>> {
pub(crate) fn days_in_month(year: i32, month: u32, first_day: Weekday) -> Vec<Vec<NaiveDate>> {
let mut year = year;
let mut month = month;
if month > 12 {
Expand All @@ -42,7 +42,8 @@ pub(crate) fn days_in_month(year: i32, month: u32) -> Vec<Vec<NaiveDate>> {

let date = NaiveDate::from_ymd_opt(year, month, 1).unwrap();
let num_days = date.days_in_month();
let start_weekday = date.weekday().num_days_from_sunday();
let start_weekday =
(date.weekday().num_days_from_sunday() + 7 - first_day.num_days_from_sunday()) % 7;

// Get the days in the month, 2023-02 will returns
// "29|30|31| 1| 2| 3| 4",
Expand Down Expand Up @@ -87,7 +88,7 @@ pub(crate) fn days_in_month(year: i32, month: u32) -> Vec<Vec<NaiveDate>> {

#[cfg(test)]
mod tests {
use chrono::{Datelike, NaiveDate};
use chrono::{Datelike, NaiveDate, Weekday};

use super::{days_in_month, NaiveDateExt};

Expand Down Expand Up @@ -115,7 +116,7 @@ mod tests {
fn test_days() {
#[track_caller]
fn assert_case(date: NaiveDate, expected: Vec<&str>) {
let out = days_in_month(date.year(), date.month())
let out = days_in_month(date.year(), date.month(), Weekday::Sun)
.iter()
.map(|week| {
week.iter()
Expand Down
Loading