对时间处理的实际使用实例

上一篇讲到 在后端date 和 timestamp处理的区别 

本篇来了解一下对时间处理的实际使用实例 (以下代码只是做演示使用,各位看官仅做参考作用 )

实例一:

日历接口的前台适配 , 数据库已经查出10月 3,5,7,15有接待数据,没有接待数据默认不展示,但是给前端的数据必须是一个完整的日历格式,而且时间区间范围是  这个月的前15天前到下个月的15号,因此需要在Java中处理时,以日期为HashKey值,Value值,数据库有数据为1,没有数据默认为0,而且需要补齐其他数据库没有的时间

实例一代码实现:

实现的基础方法如下

/**
     *前台适配.填充没有的数据,处理成日历的样式
     * @param stringTimeSet 数据库查出的具体接待日期数据
     * @param fifteenDaysAgo 这个月 前一月往前的时间
     * @param fifteenDaysLater这个月 后一月往后的时间
     * @return
     */
    public List<LinkedHashMap<Integer ,String>> fillDateStates(LinkedHashSet<String> stringTimeSet , String fifteenDaysAgo, String fifteenDaysLater){
        if(stringTimeSet.size()<0){return null;}
        final String showCalenderStates="1";
        final String dontShowCalenderStates="0";
        LinkedHashMap<Integer ,String> fillDaysStatesMap=new LinkedHashMap<>();

        int addDays=0;
        Boolean flag=true;
        while (true){
            //时间按天数自增
            String nextStringDay=addDay(fifteenDaysAgo , addDays);

            if( flag && stringTimeSet.contains(nextStringDay)){
                int nextIntegerDay=Integer.parseInt( nextStringDay.replaceAll("-" , ""));

                //数据库中查出有数据,存储展示标志位 showCalenderStates
                fillDaysStatesMap.put(nextIntegerDay ,showCalenderStates);
                stringTimeSet.remove(nextStringDay);
                if( stringTimeSet.size()==0){
                    flag=false;  //集合为空结束循环
                }
            }else{
                int nextIntegerDay=Integer.parseInt( nextStringDay.replaceAll("-" ,""));
                //数据库中没有查出有数据,存储展示标志位 dontShowCalenderStates
                fillDaysStatesMap.put( nextIntegerDay ,dontShowCalenderStates);
            }

            if( fifteenDaysLater.equals(nextStringDay)){
                break;//自增天数和日历展示最后时间相等
            }
            addDays++;
        }
        List<LinkedHashMap<Integer ,String>> fillDateStatesList=new ArrayList<>();
        fillDateStatesList.add(fillDaysStatesMap);

        return fillDateStatesList;
    }

     /**
     * 计算某月之前一个月的提前天数的日期 或者某月后一月的延后日期
     * @param stringTime 某月的具体时间
     * @param addDays 提前或者延后的时间 提前为 - (负数) ,延后为 +  (正数)
     * @return
     */
    public String getDelayDates(String stringTime ,int addDays){
        if(! org.apache.commons.lang.StringUtils.isNotBlank(stringTime) ){
            return null ;
        }
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyyMM");
        Calendar calendar=Calendar.getInstance();
        try {
            calendar.setTime(dateFormat.parse(stringTime));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if(addDays <=0){//小于0,将时间转换为改月第一天
            calendar.add(Calendar.MONTH,0);
            calendar.set(Calendar.DAY_OF_MONTH,1);
        }else {//大于0 将时间转换为该月最后一天
            calendar.set(Calendar.DAY_OF_MONTH,calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
        }
        dateFormat=new SimpleDateFormat("yyyy-MM-dd");
        String firstDayOfMonth=dateFormat.format(calendar.getTime());
        System.out.println("firstDayOfMonth "+firstDayOfMonth);
        return  addDay(firstDayOfMonth,addDays);
    }


    /**
     * 在某一天的基础上增加具体天数
     * @param stringTime
     * @param addDays
     * @return
     */
    public String addDay(String stringTime ,int addDays){
        if( addDays==0){
            return stringTime;
        }
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar=Calendar.getInstance();
        try {
            calendar.setTime(dateFormat.parse(stringTime));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        calendar.add(Calendar.DATE ,addDays);//增加一天
        //calendar.add(Calendar.MONTH ,addDays);//增加一月
        return dateFormat.format(calendar.getTime());
    }

    /**
     * 计算两个时间的间隔日期具体天数
     * @param stringTime
     * @param endTime
     * @return
     */
    public int intervalDays(String stringTime ,String endTime){
        SimpleDateFormat dateFormat=new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar=Calendar.getInstance();
        try {
            calendar.setTime(dateFormat.parse(stringTime));
        } catch (ParseException e) {
            e.printStackTrace();
        }
        int addDays=1;
        while ( true ){
            String newStringDay=addDay(stringTime,addDays);
            if(newStringDay.equals(endTime)){
                break;
            }
            addDays++;
        }
        return addDays;
    }

前台传递一个查询10月份的预定需求请求,传进来的时间为 201810 ,对时间处理,取10月之前一个月的15天和10月之后一个月之后的15天 , 具体的调用方法

System.out.println("---  +15---- "+ new Test().getDelayDates("201806",15));
System.out.println("---  -15---- "+ new Test().getDelayDates("201806",-15));

        LinkedHashSet<String> stringTimeSet=new LinkedHashSet<>();
        stringTimeSet.add("2018-06-16");
        stringTimeSet.add("2018-06-25");
        stringTimeSet.add("2018-06-27");
        stringTimeSet.add("2018-06-28");
        stringTimeSet.add("2018-06-29");
        stringTimeSet.add("2018-07-03");
        stringTimeSet.add("2018-07-05");
        stringTimeSet.add("2018-07-06");
        stringTimeSet.add("2018-07-07");
        stringTimeSet.add("2018-08-15");

        System.out.println("日历样子 "+ new Test().fillDateStates(stringTimeSet,"2018-06-16","2018-08-15").toString());

实例二:

计算某个月的非周末日期,以及可以根据自定义时间进行过滤

实例二实现:

该实例在Java后台实现问题也不大,但是本人在百度之后发现,使用Sql可以一条语句解决,所以就直接调用数据库 from dual表生成

--查询某月非工作日所有日期
 SELECT to_char( dt , 'yyyymmdd') from (select to_date(to_char(TO_DATE('20180801' ,'yyyymmdd') + LEVEL - 1 , 'yyyymmdd'),'yyyyMMdd') dt
 FROM DUAL CONNECT BY LEVEL <= to_number(to_char(LAST_DAY(TO_DATE('20180801' ,'yyyymmdd')),'dd') )) 
 WHERE 1=1 
 AND to_char(dt,'d') NOT IN (1,7)
 AND to_char(dt,'yyyymmdd') NOT IN ('20180801','20180803')
 ----level 是一个伪例  
 SELECT LEVEL FROM dual CONNECT BY LEVEL <=10  
 --获取某月最后一天
 select LAST_DAY(TO_DATE('20180801' ,'yyyymmdd'))  from dual 

 

其中level 是一个伪例 , 做循环使用 , LAST_DAY() 为获取某月最后一天 ,其中两个AND条件,可以在XML中检测参数是否为空来实现选择执行

实例三:

类似于超市统计每半个小时为单位的当前人流量, 例如 , A进入超市的时间是 8:00 离开的时间是 10:00 , 那么该超市购物时间是8:00-10:00 ,也就是说数据库记录的时间, B 在超市购物的时间是 8:30-9:00 , 此时统计数据为 8:00-8:30  1人 , 8:30-9:00   2人 , 9:00-9:30 1人 .....

实例三实现:

这里也是使用level 做一个循环 , 不断拿开始时间和结束时间的区间进行比对,之后进行统计,先看Sql实现


---半小时区间 前后时间区间统计可以的
SELECT to_char(d.dt,'yyyy-MM-dd HH24:mi:ss' ),
(    SELECT count(1) AS num 
    FROM A_HY_LOCATE3  i 
    WHERE  1=1 AND i.created_time<= (d.dt+(1/24)/2-(1/24)/3600)
    AND i.update_TIME  >=(d.dt+(1/24)/2-(1/24)/3600)
)
FROM 
(
    (SELECT to_date('20180801','yyyyMMdd')+(LEVEL-1)*((1/24)/2)  dt
    from dual connect by level <= 48) d
)

1. 其中开始时间 i.created_time 和结束时间 i.update_TIME 均减一分钟,使下一个半点时间落在下一统计区间,如00:00-00:30 的人数落在00:00这一统计里面,00:30-1:00落在00:30里,采取前闭后开,既 >=00:30  and  <01:00

2. 关于时间的加减运算

select to_char(to_date('20180810','yyyyMMdd')-((1/24)/2/1800),'yyyy-MM-dd HH24:mi:ss'),to_char(to_date('20180810','yyyyMMdd'),'yyyy-MM-dd HH24:mi:ss')from dual

该语句查询的结果

可以看出第一个结果在原来的基础上减少了1秒钟,所以时间的加减法就是按照一天24小时计算 , 简单解析一下((1/24)/2/1800) 

1/24  把一天分成24小时 这里代表一个小时

(1/24)/2 在分成24小时的基础上以半小时为单位把一天分成48份 , 这里代表半个小时

(1/24)/2/1800 把一天分成具体的秒数,这里代表1秒

所以这里的to_date('20180810','yyyyMMdd')-((1/24)/2/1800) 就是在原来基础上减1秒

3. 关于level以半小时为区间循环

SELECT to_char(to_date('20180801','yyyyMMdd')+(LEVEL-1)*((1/24)/2),'yyyyMMdd HH24:mi:ss')  dt
from dual connect by level <= 48

4. 建表语句 以及插入Sql

 create table A_HY_LOCATE3
(
  MOBILE_NO          VARCHAR2(32),
  LOCATE_TYPE        NUMBER(4),
  AREA_NO            VARCHAR2(32),
  created_time       date,
  update_TIME       DATE,
  area_name          VARCHAR2(512)
)

 INSERT INTO A_HY_LOCATE3 VALUES ('1',1,'1',to_date('2018-08-01 00:00:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 00:30:00' ,'yyyy-MM-dd HH24:mi:ss'),'1');
 INSERT INTO A_HY_LOCATE3 VALUES ('2',2,'2',to_date('2018-08-01 00:00:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 01:00:00' ,'yyyy-MM-dd HH24:mi:ss'),'2');
 
 INSERT INTO A_HY_LOCATE3 VALUES ('1',1,'1',to_date('2018-08-01 23:00:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 23:30:00' ,'yyyy-MM-dd HH24:mi:ss'),'1');
 INSERT INTO A_HY_LOCATE3 VALUES ('2',2,'2',to_date('2018-08-01 23:00:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-02 00:00:00' ,'yyyy-MM-dd HH24:mi:ss'),'2');
 
 INSERT INTO A_HY_LOCATE3 VALUES ('1',1,'1',to_date('2018-08-01 00:30:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 01:30:00' ,'yyyy-MM-dd HH24:mi:ss'),'1');
 INSERT INTO A_HY_LOCATE3 VALUES ('2',2,'2',to_date('2018-08-01 00:30:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 01:00:00' ,'yyyy-MM-dd HH24:mi:ss'),'2');
 INSERT INTO A_HY_LOCATE3 VALUES ('3',3,'3',to_date('2018-08-01 01:30:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 02:00:00' ,'yyyy-MM-dd HH24:mi:ss'),'3');
 insert into A_HY_LOCATE3 values ('4',4,'4',to_date('2018-08-01 01:00:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 02:30:00' ,'yyyy-MM-dd HH24:mi:ss'),'4');
 
 
 INSERT INTO A_HY_LOCATE3 VALUES ('5',5,'5',to_date('2018-08-01 16:00:00' ,'yyyy-MM-dd HH24:mi:ss'),to_date('2018-08-01 17:00:00' ,'yyyy-MM-dd HH24:mi:ss'),'5');

实例四:

在这里插入一个在Java中对时间循环的坑(如何在java中区分今天00:00和第二天00:00)

因为在数据库中,23:30加半小时是加一天的零点,既假如输入时 2080810 23:30 ,加半小时是20180811 00:00 ,而不是我们一般理解的24:00 , 那么如果在Java中使用while语句循环

while(time == "24:00"){}这样 的语句是永远不会结束循环的,因为时间里只有00:00 ,没有24:00,

如果改成while(time == "00:00"){}那么我输入的时间是00:00呢? 本来是要到下一天的24:00才结束循环,结果刚进就结束了.

其实在此有一个规避今天00:00 和第二天00:00的方法,

用三目运算,如果是今天的输入的时间是00:00 ,把时间替换成 -00:00 ,没错,就是在今天输入的时间中加负号,试试会有奇迹哦,一般人可不告诉他

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值