dataforge/generators/
datetime.rs

1//! 日期时间生成器模块
2
3use chrono::{DateTime, Duration, NaiveDate, Utc, Datelike};
4use rand::Rng;
5use rand::seq::SliceRandom;
6
7/// 生成指定范围内的随机日期时间
8pub fn datetime_range(start: DateTime<Utc>, end: DateTime<Utc>) -> DateTime<Utc> {
9    let mut rng = rand::thread_rng();
10    let secs = end.timestamp() - start.timestamp();
11    let random_secs = rng.gen_range(0..secs);
12    start + Duration::seconds(random_secs)
13}
14
15/// 生成过去N天内的随机日期时间
16pub fn datetime_past_days(days: i64) -> DateTime<Utc> {
17    let now = Utc::now();
18    let past = now - Duration::days(days);
19    datetime_range(past, now)
20}
21
22/// 生成未来N天内的随机日期时间
23pub fn datetime_future_days(days: i64) -> DateTime<Utc> {
24    let now = Utc::now();
25    let future = now + Duration::days(days);
26    datetime_range(now, future)
27}
28
29/// 生成今年内的随机日期
30pub fn datetime_this_year() -> DateTime<Utc> {
31    let now = Utc::now();
32    let year = now.year();
33    let start = NaiveDate::from_ymd_opt(year, 1, 1)
34        .unwrap()
35        .and_hms_opt(0, 0, 0)
36        .unwrap()
37        .and_utc();
38    let end = NaiveDate::from_ymd_opt(year, 12, 31)
39        .unwrap()
40        .and_hms_opt(23, 59, 59)
41        .unwrap()
42        .and_utc();
43    datetime_range(start, end)
44}
45
46/// 生成生日日期(18-80岁之间)
47pub fn birthday() -> String {
48    let now = Utc::now();
49    let min_age = 18;
50    let max_age = 80;
51    
52    let mut rng = rand::thread_rng();
53    let age = rng.gen_range(min_age..=max_age);
54    
55    let birth_year = now.year() - age;
56    let birth_month = rng.gen_range(1..=12);
57    let birth_day = rng.gen_range(1..=28); // 简化处理,避免月份天数问题
58    
59    NaiveDate::from_ymd_opt(birth_year, birth_month, birth_day)
60        .unwrap()
61        .format("%Y-%m-%d")
62        .to_string()
63}
64
65/// 生成工作时间(9:00-18:00)
66pub fn work_time() -> String {
67    let mut rng = rand::thread_rng();
68    let hour = rng.gen_range(9..18);
69    let minute = rng.gen_range(0..60);
70    format!("{:02}:{:02}", hour, minute)
71}
72
73/// 生成时间戳
74pub fn timestamp() -> i64 {
75    Utc::now().timestamp()
76}
77
78/// 生成RFC2822格式的日期时间字符串
79pub fn rfc2822() -> String {
80    Utc::now().to_rfc2822()
81}
82
83/// 生成指定范围内的日期
84pub fn date_between(start: &str, end: &str) -> String {
85    let mut rng = rand::thread_rng();
86    let start_date = NaiveDate::parse_from_str(start, "%Y-%m-%d").unwrap();
87    let end_date = NaiveDate::parse_from_str(end, "%Y-%m-%d").unwrap();
88    let days_diff = end_date.signed_duration_since(start_date).num_days();
89    let random_days = rng.gen_range(0..=days_diff);
90    let result_date = start_date + chrono::Duration::days(random_days);
91    result_date.format("%Y-%m-%d").to_string()
92}
93
94/// 生成时间字符串(HH:MM:SS)
95pub fn time() -> String {
96    let mut rng = rand::thread_rng();
97    let hour = rng.gen_range(0..24);
98    let minute = rng.gen_range(0..60);
99    let second = rng.gen_range(0..60);
100    format!("{:02}:{:02}:{:02}", hour, minute, second)
101}
102
103/// 生成日期时间字符串(YYYY-MM-DD HH:MM:SS)
104pub fn datetime() -> String {
105    let date = birthday();
106    let time_str = time();
107    format!("{} {}", date, time_str)
108}
109
110/// 生成星期几
111pub fn weekday() -> String {
112    let mut rng = rand::thread_rng();
113    let weekdays = ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"];
114    weekdays.choose(&mut rng).unwrap().to_string()
115}
116
117/// 生成月份
118pub fn month() -> String {
119    let mut rng = rand::thread_rng();
120    let months = ["January", "February", "March", "April", "May", "June",
121                  "July", "August", "September", "October", "November", "December"];
122    months.choose(&mut rng).unwrap().to_string()
123}
124
125/// 生成ISO 8601格式的日期时间字符串
126pub fn iso8601() -> String {
127    Utc::now().to_rfc3339()
128}
129
130/// 生成指定范围内的随机日期
131pub fn random_date_between(start: &str, end: &str) -> String {
132    date_between(start, end)
133}
134
135/// 生成日期(ISO格式)
136pub fn date_iso() -> String {
137    Utc::now().format("%Y-%m-%d").to_string()
138}
139
140#[cfg(test)]
141mod tests {
142    use super::*;
143
144    #[test]
145    fn test_datetime_past_days() {
146        let dt = datetime_past_days(30);
147        let now = Utc::now();
148        assert!(dt < now);
149        assert!(dt > now - Duration::days(30));
150    }
151
152    #[test]
153    fn test_birthday() {
154        let birth_str = birthday();
155        let birth_date = NaiveDate::parse_from_str(&birth_str, "%Y-%m-%d").unwrap();
156        let now = Utc::now();
157        let age = now.year() - birth_date.year();
158        assert!(age >= 18 && age <= 80);
159    }
160
161    #[test]
162    fn test_work_time() {
163        let time = work_time();
164        assert!(time.contains(':'));
165        let parts: Vec<&str> = time.split(':').collect();
166        assert_eq!(parts.len(), 2);
167        
168        let hour: u32 = parts[0].parse().unwrap();
169        assert!(hour >= 9 && hour < 18);
170    }
171}