feat: add analytics date dimension bindings
Some checks failed
CI / verify (push) Has been cancelled

- lock profile task tracking scope to user

- add analytics date dimension module support and tests

- regenerate SpacetimeDB Rust bindings with private APIs
This commit is contained in:
2026-05-04 13:41:22 +08:00
committed by 历冰郁-hermes版
parent 9f3e34e81a
commit 5c7c039e52
253 changed files with 14783 additions and 1462 deletions

View File

@@ -0,0 +1,148 @@
use module_runtime::{
AnalyticsDateDimensionSnapshot, RuntimeProfileFieldError,
build_analytics_date_dimension_from_date_key, parse_analytics_calendar_date_key,
validate_analytics_date_dimension_date_key,
};
fn dimension(calendar_date: &str) -> AnalyticsDateDimensionSnapshot {
let date_key = parse_analytics_calendar_date_key(calendar_date).expect("日期应可解析");
build_analytics_date_dimension_from_date_key(date_key)
}
fn date_key(calendar_date: &str) -> i64 {
parse_analytics_calendar_date_key(calendar_date).expect("日期应可解析")
}
#[test]
fn analytics_date_dimension_handles_leap_day() {
// 中文注释2024 是闰年2 月应包含 29 日且属于 ISO 第 9 周。
let snapshot = dimension("2024-02-29");
assert_eq!(snapshot.calendar_date, "2024-02-29");
assert_eq!(snapshot.weekday, 4);
assert_eq!(snapshot.iso_week_key, 202409);
assert_eq!(snapshot.week_start_date_key, date_key("2024-02-26"));
assert_eq!(snapshot.week_end_date_key, date_key("2024-03-03"));
assert_eq!(snapshot.month_key, 202402);
assert_eq!(snapshot.month_start_date_key, date_key("2024-02-01"));
assert_eq!(snapshot.month_end_date_key, date_key("2024-02-29"));
assert_eq!(snapshot.quarter_key, 20241);
assert_eq!(snapshot.year_key, 2024);
}
#[test]
fn analytics_date_dimension_uses_iso_week_year_across_year_boundary() {
// 中文注释2025-12-29 是周一,但 ISO week-year 已经进入 2026-W01。
let snapshot = dimension("2025-12-29");
assert_eq!(snapshot.calendar_date, "2025-12-29");
assert_eq!(snapshot.weekday, 1);
assert_eq!(snapshot.iso_week_key, 202601);
assert_eq!(snapshot.week_start_date_key, date_key("2025-12-29"));
assert_eq!(snapshot.week_end_date_key, date_key("2026-01-04"));
assert_eq!(snapshot.month_key, 202512);
assert_eq!(snapshot.quarter_key, 20254);
assert_eq!(snapshot.year_key, 2025);
}
#[test]
fn analytics_date_dimension_handles_new_year_inside_iso_week() {
// 中文注释2026-01-01 仍落在 2026-W01周范围跨自然年。
let snapshot = dimension("2026-01-01");
assert_eq!(snapshot.calendar_date, "2026-01-01");
assert_eq!(snapshot.weekday, 4);
assert_eq!(snapshot.iso_week_key, 202601);
assert_eq!(snapshot.week_start_date_key, date_key("2025-12-29"));
assert_eq!(snapshot.week_end_date_key, date_key("2026-01-04"));
assert_eq!(snapshot.month_key, 202601);
assert_eq!(snapshot.month_start_date_key, date_key("2026-01-01"));
assert_eq!(snapshot.month_end_date_key, date_key("2026-01-31"));
assert_eq!(snapshot.quarter_key, 20261);
assert_eq!(snapshot.year_key, 2026);
}
#[test]
fn analytics_date_dimension_handles_q1_end() {
// 中文注释Q1 结束日应映射到 2026Q1季度边界为 1 月 1 日到 3 月 31 日。
let snapshot = dimension("2026-03-31");
assert_eq!(snapshot.calendar_date, "2026-03-31");
assert_eq!(snapshot.weekday, 2);
assert_eq!(snapshot.iso_week_key, 202614);
assert_eq!(snapshot.month_key, 202603);
assert_eq!(snapshot.month_start_date_key, date_key("2026-03-01"));
assert_eq!(snapshot.month_end_date_key, date_key("2026-03-31"));
assert_eq!(snapshot.quarter_key, 20261);
assert_eq!(snapshot.quarter_start_date_key, date_key("2026-01-01"));
assert_eq!(snapshot.quarter_end_date_key, date_key("2026-03-31"));
assert_eq!(snapshot.year_key, 2026);
}
#[test]
fn analytics_date_dimension_handles_q2_start() {
// 中文注释Q2 开始日应映射到 2026Q2季度边界为 4 月 1 日到 6 月 30 日。
let snapshot = dimension("2026-04-01");
assert_eq!(snapshot.calendar_date, "2026-04-01");
assert_eq!(snapshot.weekday, 3);
assert_eq!(snapshot.iso_week_key, 202614);
assert_eq!(snapshot.month_key, 202604);
assert_eq!(snapshot.month_start_date_key, date_key("2026-04-01"));
assert_eq!(snapshot.month_end_date_key, date_key("2026-04-30"));
assert_eq!(snapshot.quarter_key, 20262);
assert_eq!(snapshot.quarter_start_date_key, date_key("2026-04-01"));
assert_eq!(snapshot.quarter_end_date_key, date_key("2026-06-30"));
assert_eq!(snapshot.year_key, 2026);
}
#[test]
fn analytics_date_dimension_handles_year_end() {
// 中文注释2026 年末属于 2026-W53且所有自然年边界应保持在 2026 年内。
let snapshot = dimension("2026-12-31");
assert_eq!(snapshot.calendar_date, "2026-12-31");
assert_eq!(snapshot.weekday, 4);
assert_eq!(snapshot.iso_week_key, 202653);
assert_eq!(snapshot.week_start_date_key, date_key("2026-12-28"));
assert_eq!(snapshot.week_end_date_key, date_key("2027-01-03"));
assert_eq!(snapshot.month_key, 202612);
assert_eq!(snapshot.month_start_date_key, date_key("2026-12-01"));
assert_eq!(snapshot.month_end_date_key, date_key("2026-12-31"));
assert_eq!(snapshot.quarter_key, 20264);
assert_eq!(snapshot.quarter_start_date_key, date_key("2026-10-01"));
assert_eq!(snapshot.quarter_end_date_key, date_key("2026-12-31"));
assert_eq!(snapshot.year_key, 2026);
assert_eq!(snapshot.year_start_date_key, date_key("2026-01-01"));
assert_eq!(snapshot.year_end_date_key, date_key("2026-12-31"));
}
#[test]
fn analytics_date_key_parser_rejects_invalid_calendar_dates() {
// 中文注释:非法日期和非 YYYY-MM-DD 字符串都必须解析失败,避免写入脏维表。
assert_eq!(
parse_analytics_calendar_date_key("2026-02-30"),
Err(RuntimeProfileFieldError::InvalidAnalyticsCalendarDate)
);
assert_eq!(
parse_analytics_calendar_date_key("bad"),
Err(RuntimeProfileFieldError::InvalidAnalyticsCalendarDate)
);
}
#[test]
fn analytics_date_dimension_rejects_out_of_supported_range() {
// 中文注释:维表只允许受控业务日期范围,避免裸 date_key 极值进入 reducer 日历算法。
assert_eq!(
parse_analytics_calendar_date_key("1999-12-31"),
Err(RuntimeProfileFieldError::InvalidAnalyticsCalendarDate)
);
assert_eq!(
parse_analytics_calendar_date_key("2101-01-01"),
Err(RuntimeProfileFieldError::InvalidAnalyticsCalendarDate)
);
assert_eq!(
validate_analytics_date_dimension_date_key(i64::MAX),
Err(RuntimeProfileFieldError::InvalidAnalyticsCalendarDate)
);
}