Ruby临时表达式模块:TExp
jopen
11年前
texp是Jim Weirich开发的Ruby临时表达式库,提供了模块化、可扩展的序列化语言。
临时表达式提供了一种精炼地表达重复性事件的方式。例如,每年的12月25日是圣诞节。一个代表圣诞节的临时表达式会返回真,如果日期是12月25日。
dec25 = Date.parse("Dec 25, 2008") christmas_texp.includes?(dec25) # => true christmas_texp.includes?(dec25 + 1) # => false
可以使用运算符组合临时表达式。例如,如果我有一个圣诞节的临时表达式和一个感恩节的临时表达式,我可以将它们合并成一个假日表达式:
holidays_texp = christmas_texp + thanksgiving_texp
TExp
特性
-
基本表达式
- DayOfWeek
- DayOfMonth
- Week
- Month
- Year
-
复合表达式
- AND
- OR
- NOT
- 时间窗口 </ul> </li>
-
inspect的描述人类可读
-
紧凑、可解析的编码
-
可由用户扩展的临时表达式类型
-
建构临时表达式的DSL
</ul> -
使用全局
texp
方法和块te = texp { day(1) * month("Jan") }
-
在类中include
TExp::DSL
模块include TExp::DSL te = day(1) * month("Jan")
例子
以下的例子使用了TExp DSL。DSL默认未开启,可以通过以下方式开启:
查看
TExp::DSL
模块获取所有DSL命令的完整描述。匹配周一
te = dow(:monday) te.includes?(Date.parse("Mar 3, 2008")) # => true te.includes?(Date.parse("Mar 4, 2008")) # => false te.includes?(Date.parse("Mar 10, 2008")) # => true # 等价于 te = TExp::DayOfWeek.new(Date::DAYNAMES.index("Monday")) # 变体 dow("Mon", "Tues") # 周一或周二
匹配三月的任意一天
te = month(:march) te.includes?(Date.parse("Mar 1, 2008")) # => true te.includes?(Date.parse("Mar 31, 2008")) # => true te.includes?(Date.parse("Mar 15, 1995")) # => true te.includes?(Date.parse("Feb 28, 2008")) # => false # 等价于 te = TExp::Month.new(3) # 变体 month(1,2,3) # 一月、二月、三月 month("Nov", "Dec") # 十一月或十二月
匹配情人节
如果你将临时表达式看成日期的集合,那么你可以以有趣的方式组合这些集合。例如,
*
运算符会创建两个日期集合的交集,只匹配同时满足两个表达式的日期。te = day(14) * month("Feb") te.includes?(Date.parse("Feb 14, 2008")) # => true te.includes?(Date.parse("Feb 14, 2007")) # => true # 等价于 te = TExp::And.new( TExp::DayOfMonth.new(14), TExp::Month.new(2))
匹配2008年的情人节
te = day(14) * month("Feb") * year(2008) te.includes?(Date.parse("Feb 14, 2008")) # => true te.includes?(Date.parse("Feb 14, 2007")) # => false # 等价于 te = TExp::And.new( TExp::DayOfMonth.new(14), TExp::Month.new(2), TExp::Year.new(2008))
匹配多个日期
交集之外,我们可以请求两个临时表达式的并集。下面我们构建一个匹配圣诞节和新年的临时表达式:
christmas = day(25) * month("Dec") new_years = day(1) * month("Jan") holidays = christmas + new_years holidays.includes?(Date.parse("Jan 1, 2008")) # => true holidays.includes?(Date.parse("Dec 25, 2008")) # => true holidays.includes?(Date.parse("Jan 1, 2009")) # => true holidays.includes?(Date.parse("Feb 14, 2008")) # => false # 等价于 holidays = TExp::Or.new( TExp::And.new( TExp::DayOfMonth.new(25), TExp::Month(12) ), TExp::And.new( TExp::DayOfMonth.new(1), TExp::Month(1) ))
排除日期
除了月末的周五之外的其他周五都是Casual Friday:
fridays = dow(:fri) last_friday = week(:last) * dow(:fri) casual_fridays = fridays - last_friday casual_fridays.includes?(Date.new(2013, 6, 21)) # => true casual_fridays.includes?(Date.new(2013, 6, 28)) # => false
相关链接
编译 SegmentFault