《分析模式:可重用对象模型》学习笔记之四:企业财政分析中的观察和丈量06

[复制链接]
发表于 2026-10-6 10:38:13 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×

"日期区间"是一个很老也很实用的分析模式:把一段起止时间建模成一个对象,而不是散落在代码里的两个 Date 变量。这样做的好处是——区间作为一个整体可以被比较、被包含判断、被传参,边界逻辑不会散架。本文以 Java 写法讲清它的核心方法设计。

先定义:一个区间长什么样

class DateRange {
    private final MfDate start;
    private final MfDate end;
}

两个端点就够了。构造函数里用 new MfDate(...) 包一层,是为了把"外部传进来的可变日期"转成内部的稳定表示,避免调用方事后改了对象、区间跟着动。

边界处理:左闭右开,别凭感觉

日期区间的坑几乎都出在"端点算不算在内"。两种常见约定:

约定含义适合场景
左闭右开 [start, end)含开始、不含结束按天统计、时间轴分段、SQL 区间查询
左闭右闭 [start, end]两端都含合同期、有效期这类业务区间

选定一种之后写进注释、全局一致,比什么都重要。两套混用几乎必然出现"少算一天/多算一天"的 bug。

核心方法:includes

这是整个模式最关键的方法——判断某个时点是否落在这个区间内:

public boolean includes(MfDate arg) {
    return !arg.before(start) && !arg.after(end);
}

写法上用"不小于起点 且 不晚于终点"而不是 arg >= start,是为了让比较逻辑集中在一处,端点语义调整时只改方法体。

传入另一个区间也能复用同一套判断:

public boolean includes(DateRange arg) {
    return this.includes(arg.start) && this.includes(arg.end);
}
public boolean overlaps(DateRange arg) {
    return arg.includes(start) || arg.includes(end) || this.includes(arg);
}

overlaps(是否有交集)由三个条件组合出来,没有重写一遍复杂的区间相交公式,这是组合复用带来的收益。

开区间与空缺的构造

public static DateRange upTo(MfDate end) {
    return new DateRange(MfDate.PAST, end);
}
public static DateRange startingOn(MfDate start) {
    return new DateRange(start, MfDate.FUTURE);
}
public static DateRange EMPTY = new DateRange(new MfDate(2000, 4, 1), new MfDate(2000, 1, 1));

用常量 PAST / FUTURE 表示无限延伸的端点,调用方读起来就是"到某天为止""从某天开始",比传 null 再到处判空干净得多。EMPTY 用一组倒置的日期表示空区间,配合下面的判空方法。

判空与相等性

public boolean isEmpty() {
    return start.after(end);
}

@Override
public boolean equals(Object arg) {
    if (!(arg instanceof DateRange)) return false;
    DateRange other = (DateRange) arg;
    return start.equals(other.start) && end.equals(other.end);
}

@Override
public int hashCode() {
    return start.hashCode();
}

两个细节值得记住:空区间用"起止倒置"表达,不用额外布尔字段;重写 equals 必须同时重写 hashCode,否则放进 HashMap / HashSet 后行为诡异。

toString 方便排查

public String toString() {
    if (isEmpty()) return "Empty Date Range";
    return start.toString() + " - " + end.toString();
}

日志日志里直接打区间对象就能看懂,省掉一句 dateRange.getStart() + " ~ " + dateRange.getEnd()。

这套模式能用在哪

  • 统计口径统一。按天/按月/按财务期间的报表查询,全用同一个 DateRange 构造 SQL 的 BETWEEN 条件。
  • 有效期校验。合同、优惠券、订阅的有效期判断,一行 range.includes(now) 搞定。
  • 时间轴分段。把一整年切成多个区间做分桶统计,重叠判断交给 overlaps。
  • 权限/生效时间。角色、功能灰度的时间窗,用区间对象传递比两个裸时间变量安全。

一句话总结:把"两个日期"升级成"一个区间对象",边界规则收敛到一处,业务代码里就不会再到处出现 >= 和 < 的散装比较。

qidao123.com企服评测-应用市场 编辑提示

本文由齐道123 IT 运维社区整理,介绍《分析模式:可重用对象模型》中"日期区间"这一分析模式的 Java 实现思路与工程取舍。文中代码为原理示例,仅作技术讨论,不含任何第三方链接;实际项目请结合团队规范补充单元测试,尤其覆盖边界日期与空区间场景。

回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表