4个版本
0.1.3 | 2023年12月5日 |
---|---|
0.1.2 | 2023年11月30日 |
0.1.1 | 2023年11月26日 |
0.1.0 | 2023年11月26日 |
在Rust模式中排名第377
75KB
1.5K SLoC
🕗 Timelang
Timelang是一个简单的DSL(领域特定语言),用于表示人类可读的时间相关表达式,包括特定的日期时间、相对表达式(如“现在3小时后”)、时间范围和持续时间。
入门指南
要使用timelang,您应该查看[TimeExpression],它是AST的最高级入口点,或者一些更具体的类型,如[Duration]、[PointInTime]和[TimeRange]。
timelang中的所有节点都实现了[FromStr]以及syn::parse::Parse,后者用于内部解析逻辑。所有节点类型都使用标准[Display]实现作为将它们输出为字符串的首选方式。
请注意,目前timelang仅支持年、月、周、日、小时和分钟,但以后可能会添加秒等。对于timelang的许多常见用例,通常不需要比分钟分辨率更好的分辨率。
示例
以下都是timelang中有效的表达式示例
now
明天
下个星期二
后天
前天
20/4/2021
11:21 上午
15/6/2022在3:58 下午
2小时, 37分钟
5年, 2月, 3周和11分钟
7天前
2年前和10现在起分钟
5天, 3周, 6分钟后15/4/2025在9:27 上午
从2023年1月1日14:07到2023年1月15日
从2024年3月19日10:07 AM到2027年3月9日5:27 PM后的3个月2天
2天和14后天后的天数和小时
11前天前的天数
5下个星期二后的天数
特定日期
use timelang::*;
assert_eq!(
"20/4/2021".parse::<TimeExpression>().unwrap(),
TimeExpression::Specific(PointInTime::Absolute(AbsoluteTime::Date(Date(
Month::April,
DayOfMonth(20),
Year(2021)
))))
);
特定日期时间
use timelang::*;
assert_eq!(
"15/6/2022 at 14:00".parse::<AbsoluteTime>().unwrap(),
AbsoluteTime::DateTime(DateTime(
Date(Month::June, DayOfMonth(15), Year(2022)),
Time(Hour::Hour24(14), Minute(0))
))
);
时间范围
use timelang::*;
assert_eq!(
"from 1/1/2023 to 15/1/2023"
.parse::<TimeExpression>()
.unwrap(),
TimeExpression::Range(TimeRange(
PointInTime::Absolute(AbsoluteTime::Date(Date(
Month::January,
DayOfMonth(1),
Year(2023)
))),
PointInTime::Absolute(AbsoluteTime::Date(Date(
Month::January,
DayOfMonth(15),
Year(2023)
)))
))
);
持续时间(多个单位用逗号分隔)
use timelang::*;
assert_eq!(
"2 hours, 30 minutes".parse::<TimeExpression>().unwrap(),
TimeExpression::Duration(Duration {
hours: Number(2),
minutes: Number(30),
days: Number(0),
weeks: Number(0),
months: Number(0),
years: Number(0)
})
);
持续时间(多个单位用and
)
use timelang::*;
assert_eq!(
"1 year and 6 months".parse::<TimeExpression>().unwrap(),
TimeExpression::Duration(Duration {
years: Number(1),
months: Number(6),
days: Number(0),
weeks: Number(0),
hours: Number(0),
minutes: Number(0)
})
);
相对时间(使用ago
)
use timelang::*;
assert_eq!(
"3 days ago".parse::<TimeExpression>().unwrap(),
TimeExpression::Specific(PointInTime::Relative(RelativeTime::Directional {
duration: Duration {
days: Number(3),
minutes: Number(0),
hours: Number(0),
weeks: Number(0),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::Ago
}))
);
相对时间(使用from now
)
use timelang::*;
assert_eq!(
"5 days, 10 hours, and 35 minutes from now"
.parse::<TimeExpression>()
.unwrap(),
TimeExpression::Specific(PointInTime::Relative(RelativeTime::Directional {
duration: Duration {
minutes: Number(35),
hours: Number(10),
days: Number(5),
weeks: Number(0),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::FromNow
}))
);
相对时间(after
特定日期)
use timelang::*;
assert_eq!(
"2 hours, 3 minutes after 10/10/2022"
.parse::<TimeExpression>()
.unwrap(),
TimeExpression::Specific(PointInTime::Relative(RelativeTime::Directional {
duration: Duration {
hours: Number(2),
minutes: Number(3),
days: Number(0),
weeks: Number(0),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::AfterAbsolute(AbsoluteTime::Date(Date(
Month::October,
DayOfMonth(10),
Year(2022)
)))
}))
);
相对时间(before
特定日期时间)
use timelang::*;
assert_eq!(
"1 day before 31/12/2023 at 11:13 PM"
.parse::<TimeExpression>()
.unwrap(),
TimeExpression::Specific(PointInTime::Relative(RelativeTime::Directional {
duration: Duration {
days: Number(1),
minutes: Number(0),
hours: Number(0),
weeks: Number(0),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::BeforeAbsolute(AbsoluteTime::DateTime(DateTime(
Date(Month::December, DayOfMonth(31), Year(2023)),
Time(Hour::Hour12(11, AmPm::PM), Minute(13))
)))
}))
);
时间范围(带有特定日期时间)
use timelang::*;
assert_eq!(
"from 1/1/2024 at 10:00 to 2/1/2024 at 15:30"
.parse::<TimeExpression>()
.unwrap(),
TimeExpression::Range(TimeRange(
PointInTime::Absolute(AbsoluteTime::DateTime(DateTime(
Date(Month::January, DayOfMonth(1), Year(2024)),
Time(Hour::Hour24(10), Minute(0))
))),
PointInTime::Absolute(AbsoluteTime::DateTime(DateTime(
Date(Month::January, DayOfMonth(2), Year(2024)),
Time(Hour::Hour24(15), Minute(30))
)))
))
);
相对时间
use timelang::*;
assert_eq!("now".parse::<RelativeTime>().unwrap(), RelativeTime::Named(NamedRelativeTime::Now));
assert_eq!(
"tomorrow".parse::<RelativeTime>().unwrap(),
RelativeTime::Named(NamedRelativeTime::Tomorrow)
);
assert_eq!(
"yesterday".parse::<RelativeTime>().unwrap(),
RelativeTime::Named(NamedRelativeTime::Yesterday)
);
assert_eq!(
"day before yesterday".parse::<RelativeTime>().unwrap(),
RelativeTime::Named(NamedRelativeTime::DayBeforeYesterday)
);
// note the optional `the`
assert_eq!(
"the day after tomorrow".parse::<RelativeTime>().unwrap(),
RelativeTime::Named(NamedRelativeTime::DayAfterTomorrow)
);
assert_eq!(
"next tuesday".parse::<RelativeTime>().unwrap(),
RelativeTime::Next(RelativeTimeUnit::Tuesday)
);
assert_eq!(
"last wednesday".parse::<RelativeTime>().unwrap(),
RelativeTime::Last(RelativeTimeUnit::Wednesday)
);
assert_eq!(
"3 days before yesterday".parse::<RelativeTime>().unwrap(),
RelativeTime::Directional {
duration: Duration {
minutes: Number(0),
hours: Number(0),
days: Number(3),
weeks: Number(0),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::BeforeNamed(NamedRelativeTime::Yesterday)
}
);
assert_eq!(
"2 days and 14 hours after the day after tomorrow".parse::<RelativeTime>().unwrap(),
RelativeTime::Directional {
duration: Duration {
minutes: Number(0),
hours: Number(14),
days: Number(2),
weeks: Number(0),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::AfterNamed(NamedRelativeTime::DayAfterTomorrow)
}
);
assert_eq!(
"2 weeks before last sunday".parse::<RelativeTime>().unwrap(),
RelativeTime::Directional {
duration: Duration {
minutes: Number(0),
hours: Number(0),
days: Number(0),
weeks: Number(2),
months: Number(0),
years: Number(0)
},
dir: TimeDirection::BeforeLast(RelativeTimeUnit::Sunday)
}
);
assert_eq!(
"3 years, 2 weeks after next thursday".parse::<RelativeTime>().unwrap(),
RelativeTime::Directional {
duration: Duration {
minutes: Number(0),
hours: Number(0),
days: Number(0),
weeks: Number(2),
months: Number(0),
years: Number(3)
},
dir: TimeDirection::AfterNext(RelativeTimeUnit::Thursday)
}
);
备注
- 目前使用syn进行解析。这可能会被替换为待定的解析crate,但使用syn可以快速启动。无论我们使用哪个新的crate,都希望它能让我们让timelang与no std兼容。
- Timelang是明确的,这意味着所有可能的timelang句子都有且只有一个树表示。如果您能想出一个歧义句子,请通过提交GitHub问题告诉我们!
依赖项
~300–740KB
~18K SLoC