计算两个日期月份差,不足一月按0月算,时间不参与计算

/**
     * 计算两个日期月份差,不足一月按0月算,
     * 日期没有前后顺序,时间不参与计算
     * getMonthSub 2019.12.22 00:00:00  2019.12.23 00:00:00 0
     * getMonthSub 2019.11.23 00:00:00  2019.12.22 00:00:00 0
     * getMonthSub 2019.12.23 00:00:00  2020.12.22 00:00:00 11
     * getMonthSub 2018.11.02 00:00:00  2019.02.03 00:00:00 3
     * getMonthSub 2018.11.02 00:00:00  2019.02.01 00:00:00 2
     *
     * getMonthSub 2019.12.23 00:00:00  2019.12.22 00:00:00 0
     * getMonthSub 2019.12.22 00:00:00  2019.11.23 00:00:00 0
     * getMonthSub 2020.12.22 00:00:00  2019.12.23 00:00:00 11
     * getMonthSub 2019.02.03 00:00:00  2018.11.02 00:00:00 3
     * getMonthSub 2019.02.01 00:00:00  2018.11.02 00:00:00 2
     * @param time1     时间1
     * @param time2     时间2
     * @param format    时间格式
     * @return
     */
    public static int getMonthSub(String time1,String time2,String format)throws Exception{
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        Calendar before = Calendar.getInstance();
        Calendar after = Calendar.getInstance();
        Date beforeDate = sdf.parse(time1);
        Date afterDate = sdf.parse(time2);
        if(beforeDate.compareTo(afterDate)>0){
            before.setTime(afterDate);
            after.setTime(beforeDate);
        }else if(beforeDate.compareTo(afterDate)<0){
            before.setTime(beforeDate);
            after.setTime(afterDate);
        }else{
            return 0;
        }
        int surplus = after.get(Calendar.DATE) - before.get(Calendar.DATE);
        int result = after.get(Calendar.MONTH) - before.get(Calendar.MONTH);
        int month = (after.get(Calendar.YEAR) - before.get(Calendar.YEAR)) * 12;
        surplus = surplus < 0 ? -1 : 0;
        return  Math.abs(month + result) + surplus;
    }
public static void main(String[] args){
    try {
            System.out.println("getMonthSub 2019.12.22 00:00:00  2019.12.23 00:00:00 " + getMonthSub("2019.12.22 00:00:00", "2019.12.23 00:00:00", "yyyy.MM.dd HH:mm:ss"));//0
            System.out.println("getMonthSub 2019.11.23 00:00:00  2019.12.22 00:00:00 " + getMonthSub("2019.11.23 00:00:00", "2019.12.22 00:00:00", "yyyy.MM.dd HH:mm:ss"));//0
            System.out.println("getMonthSub 2019.12.23 00:00:00  2020.12.22 00:00:00 " + getMonthSub("2019.12.23 00:00:00", "2020.12.22 00:00:00", "yyyy.MM.dd HH:mm:ss"));//11
            System.out.println("getMonthSub 2018.11.02 00:00:00  2019.02.03 00:00:00 " + getMonthSub("2018.11.02 00:00:00", "2019.02.03 00:00:00", "yyyy.MM.dd HH:mm:ss"));//3
            System.out.println("getMonthSub 2018.11.02 00:00:00  2019.02.01 00:00:00 " + getMonthSub("2018.11.02 00:00:00", "2019.02.01 00:00:00", "yyyy.MM.dd HH:mm:ss"));//2
            System.out.println();
            System.out.println("getMonthSub 2019.12.23 00:00:00  2019.12.22 00:00:00 " + getMonthSub("2019.12.23 00:00:00", "2019.12.22 00:00:00", "yyyy.MM.dd HH:mm:ss"));//0
            System.out.println("getMonthSub 2019.12.22 00:00:00  2019.11.23 00:00:00 " + getMonthSub("2019.12.22 00:00:00", "2019.11.23 00:00:00", "yyyy.MM.dd HH:mm:ss"));//0
            System.out.println("getMonthSub 2020.12.22 00:00:00  2019.12.23 00:00:00 " + getMonthSub("2020.12.22 00:00:00", "2019.12.23 00:00:00", "yyyy.MM.dd HH:mm:ss"));//11
            System.out.println("getMonthSub 2019.02.03 00:00:00  2018.11.02 00:00:00 " + getMonthSub("2019.02.03 00:00:00", "2018.11.02 00:00:00", "yyyy.MM.dd HH:mm:ss"));//3
            System.out.println("getMonthSub 2019.02.01 00:00:00  2018.11.02 00:00:00 " + getMonthSub("2019.02.01 00:00:00", "2018.11.02 00:00:00", "yyyy.MM.dd HH:mm:ss"));//2
        }catch (Exception e){
            e.printStackTrace();
        }
}

 

### 使用 ShardingSphere-JDBC 5.2 实现按分库分表 #### 配置概述 为了实现基于月份的动态分库分表策略,ShardingSphere-JDBC 提供了灵活的配置选项和支持自定义分片法的能力[^3]。通过这些特性,可以根据时间字段自动分配数据到同的数据库和表格。 #### 数据源配置 首先需要设置多个数据源来代表同年份或时间段内的各个数据库实例: ```yaml spring: shardingsphere: datasource: names: ds_0,ds_1,...,ds_n # 假设有 n+1 个数据源对应每个的数据存储节点 ds_0: type: com.zaxxer.hikari.HikariDataSource driver-class-name: org.postgresql.Driver jdbc-url: jdbc:postgresql://localhost:5432/db_monthly_0?useSSL=false&serverTimezone=UTC username: root password: '' ... ``` #### 表结构设计 假设有一个订单表 `t_order` ,其包含创建日期列 `create_time` 。那么可以为每个创建一个新的逻辑表名模式如下所示: - t_order_yyyyMM (其中 yyyy 是四位数表示年份, MM 则是以两位数字表示月份) 例如: - 对于2023年的第一个,则实际物理表名为`t_order_202301` 这种命名方式有助于直观地区分各个月份之间的异并简化后续维护工作。 #### 分片规则设定 接下来就是定义具体的分片键以及相应的路由规则。这里采用标准精确匹配加范围查询相结合的方式来进行高效定位目标分区位置。 ```java // Java Config Example for Monthly Based Table Sharding Strategy @Bean public ShardingRuleConfiguration shardingRuleConfig() { final ShardingRuleConfiguration result = new ShardingRuleConfiguration(); // Define table rules with monthly-based pattern. List<TableRule> tableRules = Arrays.asList( TableRule.builder() .logicTable("t_order") .actualDataNodes("ds_${0..n}.t_order_${yyyyMM}") .tableStrategy(new StandardShardingStrategyConfiguration( "create_time", new DateTimeMonthBasedShardingAlgorithm())) .build()); result.getTableRuleConfigs().addAll(tableRules); return result; } ``` 在此基础上还可以进一步优化性能表现,比如引入缓存机制减少重复计算开销;或是利用广播表功能确保某些特定类型的元数据能够被所有参与的服务共享访问[^1]。 #### 自定义分片法 针对上述提到的时间戳字段 `create_time`, 可以编写一个简单的基于月份的哈希函数用于决定具体应该写入哪个子表内: ```java import java.time.LocalDateTime; class DateTimeMonthBasedShardingAlgorithm implements PreciseShardingAlgorithm<LocalDateTime>, RangeShardingAlgorithm<LocalDateTime> { @Override public String doEqualShard(final Collection<String> availableTargetNames, final PreciseShardingValue<LocalDateTime> shardingValue) { LocalDateTime createTime = shardingValue.getValue(); int monthOfYear = createTime.getMonthValue(); // Get the numeric representation of this date's month-of-year // Assuming we have a fixed number of databases per year and tables within each database represent different months, // calculate target data source name based on current time point. return getActualTableName(createTime.getYear(), monthOfYear); } private static String getActualTableName(int year, int month){ StringBuilder sb=new StringBuilder(); sb.append("t_order_").append(year).append(String.format("%02d",month)); return sb.toString(); } } ``` 此方法仅适用于插入新记录时确定合适的放置地点,在执行读取请求期间同样有效,因为它能帮助系统快速锁定所需检索的具体片段而必遍历整个集合空间。
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值