Skip to content

Commit 876a3db

Browse files
authored
feat: function extract, date_part,date_diff support more date part (#17759)
* date_diff support more date part * add typos wrong case
1 parent beb3604 commit 876a3db

File tree

9 files changed

+389
-4
lines changed

9 files changed

+389
-4
lines changed

.typos.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"flate" = "flate"
1515
"Tke" = "Tke"
1616
"typ" = "typ"
17+
"dows" = "dows"
1718

1819
[files]
1920
extend-exclude = [

src/query/ast/src/ast/expr.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -845,6 +845,9 @@ pub enum IntervalKind {
845845
Dow,
846846
Epoch,
847847
MicroSecond,
848+
ISODow,
849+
YearWeek,
850+
Millennium,
848851
}
849852

850853
impl Display for IntervalKind {
@@ -860,6 +863,9 @@ impl Display for IntervalKind {
860863
IntervalKind::Second => "SECOND",
861864
IntervalKind::Doy => "DOY",
862865
IntervalKind::Dow => "DOW",
866+
IntervalKind::ISODow => "ISODOW",
867+
IntervalKind::YearWeek => "YEARWEEK",
868+
IntervalKind::Millennium => "MILLENNIUM",
863869
IntervalKind::Week => "WEEK",
864870
IntervalKind::Epoch => "EPOCH",
865871
IntervalKind::MicroSecond => "MICROSECOND",

src/query/ast/src/parser/expr.rs

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1854,9 +1854,12 @@ pub fn interval_kind(i: Input) -> IResult<IntervalKind> {
18541854
let second = value(IntervalKind::Second, rule! { SECOND });
18551855
let doy = value(IntervalKind::Doy, rule! { DOY });
18561856
let dow = value(IntervalKind::Dow, rule! { DOW });
1857+
let isodow = value(IntervalKind::ISODow, rule! { ISODOW });
18571858
let week = value(IntervalKind::Week, rule! { WEEK });
18581859
let epoch = value(IntervalKind::Epoch, rule! { EPOCH });
18591860
let microsecond = value(IntervalKind::MicroSecond, rule! { MICROSECOND });
1861+
let millennium = value(IntervalKind::Millennium, rule! { MILLENNIUM });
1862+
let yearweek = value(IntervalKind::YearWeek, rule! { YEARWEEK });
18601863

18611864
let iso_year_str = value(
18621865
IntervalKind::ISOYear,
@@ -1892,15 +1895,19 @@ pub fn interval_kind(i: Input) -> IResult<IntervalKind> {
18921895
);
18931896
let doy_str = value(
18941897
IntervalKind::Doy,
1895-
rule! { #literal_string_eq_ignore_case("DOY") },
1898+
rule! { #literal_string_eq_ignore_case("DOY") | #literal_string_eq_ignore_case("DAYOFYEAR") },
18961899
);
18971900
let dow_str = value(
18981901
IntervalKind::Dow,
1899-
rule! { #literal_string_eq_ignore_case("DOW") },
1902+
rule! { (#literal_string_eq_ignore_case("DOW") | #literal_string_eq_ignore_case("WEEKDAY") | #literal_string_eq_ignore_case("DAYOFWEEK") ) },
1903+
);
1904+
let isodow_str = value(
1905+
IntervalKind::ISODow,
1906+
rule! { #literal_string_eq_ignore_case("ISODOW") },
19001907
);
19011908
let week_str = value(
19021909
IntervalKind::Week,
1903-
rule! { #literal_string_eq_ignore_case("WEEK") },
1910+
rule! { (#literal_string_eq_ignore_case("WEEK") | #literal_string_eq_ignore_case("WEEKS") | #literal_string_eq_ignore_case("W")) },
19041911
);
19051912
let epoch_str = value(
19061913
IntervalKind::Epoch,
@@ -1910,6 +1917,14 @@ pub fn interval_kind(i: Input) -> IResult<IntervalKind> {
19101917
IntervalKind::MicroSecond,
19111918
rule! { #literal_string_eq_ignore_case("MICROSECOND") },
19121919
);
1920+
let yearweek_str = value(
1921+
IntervalKind::YearWeek,
1922+
rule! { #literal_string_eq_ignore_case("YEARWEEK") },
1923+
);
1924+
let millennium_str = value(
1925+
IntervalKind::Millennium,
1926+
rule! { #literal_string_eq_ignore_case("MILLENNIUM") },
1927+
);
19131928
alt((
19141929
rule!(
19151930
#year
@@ -1925,6 +1940,9 @@ pub fn interval_kind(i: Input) -> IResult<IntervalKind> {
19251940
| #week
19261941
| #epoch
19271942
| #microsecond
1943+
| #isodow
1944+
| #millennium
1945+
| #yearweek
19281946
),
19291947
rule!(
19301948
#year_str
@@ -1940,6 +1958,9 @@ pub fn interval_kind(i: Input) -> IResult<IntervalKind> {
19401958
| #week_str
19411959
| #epoch_str
19421960
| #microsecond_str
1961+
| #isodow_str
1962+
| #yearweek_str
1963+
| #millennium_str
19431964
),
19441965
))(i)
19451966
}

src/query/ast/src/parser/token.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,8 @@ pub enum TokenKind {
591591
ENGINES,
592592
#[token("EPOCH", ignore(ascii_case))]
593593
EPOCH,
594+
#[token("YEARWEEK", ignore(ascii_case))]
595+
YEARWEEK,
594596
#[token("MICROSECOND", ignore(ascii_case))]
595597
MICROSECOND,
596598
#[token("ERROR_ON_COLUMN_COUNT_MISMATCH", ignore(ascii_case))]

src/query/expression/src/utils/date_helper.rs

Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -177,6 +177,52 @@ impl EvalYearsImpl {
177177
}
178178
}
179179

180+
pub struct EvalISOYearsImpl;
181+
impl EvalISOYearsImpl {
182+
pub fn eval_date_diff(date_start: i32, date_end: i32, tz: TimeZone) -> i32 {
183+
let date_start = date_start.to_date(tz.clone());
184+
let date_end = date_end.to_date(tz);
185+
date_end.iso_week_date().year() as i32 - date_start.iso_week_date().year() as i32
186+
}
187+
188+
pub fn eval_timestamp_diff(date_start: i64, date_end: i64, tz: TimeZone) -> i64 {
189+
let date_start = date_start.to_timestamp(tz.clone());
190+
let date_end = date_end.to_timestamp(tz);
191+
date_end.date().iso_week_date().year() as i64 - date_start.iso_week_date().year() as i64
192+
}
193+
}
194+
195+
pub struct EvalYearWeeksImpl;
196+
impl EvalYearWeeksImpl {
197+
pub fn eval_date_diff(date_start: i32, date_end: i32, tz: TimeZone) -> i32 {
198+
let date_start = date_start.to_date(tz.clone());
199+
let date_end = date_end.to_date(tz);
200+
let week_date = date_end.iso_week_date();
201+
let year = week_date.year() as i32 * 100;
202+
let end = year + date_end.iso_week_date().week() as i32;
203+
204+
let week_date = date_start.iso_week_date();
205+
let year = week_date.year() as i32 * 100;
206+
let start = year + date_start.iso_week_date().week() as i32;
207+
208+
end - start
209+
}
210+
211+
pub fn eval_timestamp_diff(date_start: i64, date_end: i64, tz: TimeZone) -> i64 {
212+
let date_start = date_start.to_timestamp(tz.clone());
213+
let date_end = date_end.to_timestamp(tz);
214+
let week_date = date_end.date().iso_week_date();
215+
let year = week_date.year() as i64 * 100;
216+
let end = year + date_end.date().iso_week_date().week() as i64;
217+
218+
let week_date = date_start.date().iso_week_date();
219+
let year = week_date.year() as i64 * 100;
220+
let start = year + date_start.date().iso_week_date().week() as i64;
221+
222+
end - start
223+
}
224+
}
225+
180226
pub struct EvalQuartersImpl;
181227

182228
impl EvalQuartersImpl {
@@ -351,16 +397,21 @@ impl ToNumberImpl {
351397
}
352398

353399
pub struct ToYYYYMM;
400+
pub struct ToYYYYWW;
354401
pub struct ToYYYYMMDD;
355402
pub struct ToYYYYMMDDHH;
356403
pub struct ToYYYYMMDDHHMMSS;
357404
pub struct ToYear;
405+
pub struct ToTimezoneHour;
406+
pub struct ToTimezoneMinute;
407+
pub struct ToMillennium;
358408
pub struct ToISOYear;
359409
pub struct ToQuarter;
360410
pub struct ToMonth;
361411
pub struct ToDayOfYear;
362412
pub struct ToDayOfMonth;
363413
pub struct ToDayOfWeek;
414+
pub struct DayOfWeek;
364415
pub struct ToHour;
365416
pub struct ToMinute;
366417
pub struct ToSecond;
@@ -374,6 +425,12 @@ impl ToNumber<u32> for ToYYYYMM {
374425
}
375426
}
376427

428+
impl ToNumber<u16> for ToMillennium {
429+
fn to_number(dt: &Zoned) -> u16 {
430+
dt.year() as u16 / 1000 + 1
431+
}
432+
}
433+
377434
impl ToNumber<u32> for ToWeekOfYear {
378435
fn to_number(dt: &Zoned) -> u32 {
379436
dt.date().iso_week_date().week() as u32
@@ -412,12 +469,32 @@ impl ToNumber<u16> for ToYear {
412469
}
413470
}
414471

472+
impl ToNumber<i16> for ToTimezoneHour {
473+
fn to_number(dt: &Zoned) -> i16 {
474+
dt.offset().seconds().div_ceil(3600) as i16
475+
}
476+
}
477+
478+
impl ToNumber<i16> for ToTimezoneMinute {
479+
fn to_number(dt: &Zoned) -> i16 {
480+
(dt.offset().seconds() % 3600).div_ceil(60) as i16
481+
}
482+
}
483+
415484
impl ToNumber<u16> for ToISOYear {
416485
fn to_number(dt: &Zoned) -> u16 {
417486
dt.date().iso_week_date().year() as _
418487
}
419488
}
420489

490+
impl ToNumber<u32> for ToYYYYWW {
491+
fn to_number(dt: &Zoned) -> u32 {
492+
let week_date = dt.date().iso_week_date();
493+
let year = week_date.year() as u32 * 100;
494+
year + dt.date().iso_week_date().week() as u32
495+
}
496+
}
497+
421498
impl ToNumber<u8> for ToQuarter {
422499
fn to_number(dt: &Zoned) -> u8 {
423500
// begin with 0
@@ -449,6 +526,12 @@ impl ToNumber<u8> for ToDayOfWeek {
449526
}
450527
}
451528

529+
impl ToNumber<u8> for DayOfWeek {
530+
fn to_number(dt: &Zoned) -> u8 {
531+
dt.weekday().to_sunday_zero_offset() as u8
532+
}
533+
}
534+
452535
impl ToNumber<i64> for ToUnixTimestamp {
453536
fn to_number(dt: &Zoned) -> i64 {
454537
dt.with_time_zone(TimeZone::UTC).timestamp().as_second()

0 commit comments

Comments
 (0)