lixing 3 anni fa
parent
commit
1d787cfc7a

+ 2 - 2
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/dto/AlarmCondition.java

@@ -1,7 +1,7 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.dto;
 
+import com.alibaba.fastjson.JSONObject;
 import lombok.Data;
-import org.springframework.boot.configurationprocessor.json.JSONObject;
 
 import java.util.List;
 
@@ -36,5 +36,5 @@ public class AlarmCondition {
     /**
      * 存储用户自定义的配置
      */
-    private String configs;
+    private JSONObject configs;
 }

+ 15 - 12
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/dto/alarmrecord/AddAlarmRecordDTO.java

@@ -1,5 +1,7 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord;
 
+import com.alibaba.fastjson.JSONObject;
+import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.apm.energyalarmstarter.alarmdata.feign.AlarmUrlParam;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
@@ -63,14 +65,23 @@ public class AddAlarmRecordDTO extends AlarmUrlParam {
      * 处理状态
      */
     private Integer treatState;
+
+    /**
+     * 有效期开始时间
+     */
+    private Date effectStartTime;
+    /**
+     * 有效期结束时间
+     */
+    private Date effectEndTime;
     /**
      * 报警发生时的报警条件
      */
-    private String condition;
+    private JSONObject condition;
     /**
      * 报警发生时的采集值信息
      */
-    private String triggerInfo;
+    private JSONObject triggerInfo;
     /**
      * 报警发生时间
      */
@@ -78,7 +89,7 @@ public class AddAlarmRecordDTO extends AlarmUrlParam {
     /**
      * 报警恢复时的采集值信息
      */
-    private String endInfo;
+    private JSONObject endInfo;
     /**
      * 报警恢复时间
      */
@@ -86,7 +97,7 @@ public class AddAlarmRecordDTO extends AlarmUrlParam {
     /**
      * 补充说明
      */
-    private String supplement;
+    private JSONObject supplement;
     /**
      * 工单id
      */
@@ -95,12 +106,4 @@ public class AddAlarmRecordDTO extends AlarmUrlParam {
      * 工单状态
      */
     private String orderState;
-    /**
-     * 忽略报警时间
-     */
-    private Date ignoreTime;
-    /**
-     * 报警处理完成时间
-     */
-    private Date treatEndTime;
 }

+ 81 - 34
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/dto/alarmrecord/QueryAlarmRecordDTO.java

@@ -1,7 +1,8 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord;
 
-import com.fasterxml.jackson.databind.node.ObjectNode;
+import com.alibaba.fastjson.JSONObject;
 import com.persagy.apm.energyalarmstarter.alarmdata.feign.AlarmUrlParam;
+import com.persagy.apm.energyalarmstarter.alarmdata.utils.DateUtils;
 import lombok.Data;
 import lombok.EqualsAndHashCode;
 
@@ -17,53 +18,99 @@ import java.util.List;
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class QueryAlarmRecordDTO extends AlarmUrlParam {
-    private String id;
-    private String itemCode;
-    private String projectId;
-    private String objId;
-    private String classCode;
-    private String level;
+    /**
+     * 报警记录id
+     */
+    private List<String> id;
+    /**
+     * 报警条目编码
+     */
+    private List<String> itemCode;
+    /**
+     * 报警对象id
+     */
+    private List<String> objId;
+    /**
+     * 设备类编码
+     */
+    private List<String> classCode;
+    /**
+     * 报警等级
+     */
+    private List<String> level;
+    /**
+     * 备注
+     */
     private String remark;
+    /**
+     * 报警名称
+     */
     private String name;
-    private String category;
-    private Integer concern;
-    private Integer state;
-    private Date effectStartTime;
-    private Date effectEndTime;
+    /**
+     * 报警系统
+     */
+    private List<String> category;
+    /**
+     * 报警状态
+     */
+    private List<Integer> state;
     /**
      * 报警性质
      */
-    private Integer nature;
+    private List<Integer> nature;
     /**
      * 处理方式
      */
-    private Integer treatMode;
+    private List<Integer> treatMode;
     /**
      * 处理状态
      */
-    private Integer treatState;
-    private String createUser;
-    private ObjectNode condition;
-    private ObjectNode triggerInfo;
+    private List<Integer> treatState;
+    /**
+     * 报警发生时间
+     */
     private Date triggerTime;
-    private ObjectNode endInfo;
-    private Date endTime;
-    private Date createTime;
-    private String updateUser;
-    private Date updateTime;
-    private Integer valid;
-    private String groupCode;
-    private String orderId;
-    private String orderState;
-    private ObjectNode supplement;
-
     /**
-     * 忽略报警时间
+     * 报警发生时间区间-起始时间
      */
-    private Date ignoreTime;
+    private Date triggerDurationStart;
     /**
-     * 报警处理完成时间
+     * 报警发生时间区间-结束时间
      */
-    private Date treatEndTime;
-    private String targetId;
+    private Date triggerDurationEnd;
+    /**
+     * 工单id
+     */
+    private List<String> orderId;
+    /**
+     * 工单状态
+     */
+    private List<String> orderState;
+
+    public JSONObject getName() {
+        if (this.name == null) {
+            return null;
+        }
+        JSONObject jsonObject = new JSONObject();
+        jsonObject.put("$like", this.name);
+        return jsonObject;
+    }
+
+    public Object getTriggerTime() {
+        if (this.triggerTime != null) {
+            return DateUtils.date2Str(this.triggerTime, DateUtils.SDF_SECOND);
+        }
+
+        if (this.triggerDurationStart !=null || this.triggerDurationEnd != null) {
+            JSONObject jsonObject = new JSONObject();
+            if (this.triggerDurationStart !=null) {
+                jsonObject.put("$gte", DateUtils.date2Str(this.triggerDurationStart, DateUtils.SDF_SECOND));
+            }
+            if (this.triggerDurationEnd !=null) {
+                jsonObject.put("$lte", DateUtils.date2Str(this.triggerDurationEnd, DateUtils.SDF_SECOND));
+            }
+            return jsonObject;
+        }
+        return null;
+    }
 }

+ 31 - 27
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/dto/alarmrecord/UpdateAlarmRecordDTO.java

@@ -1,5 +1,6 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord;
 
+import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.apm.energyalarmstarter.alarmdata.feign.AlarmUrlParam;
 import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
@@ -19,19 +20,22 @@ import java.util.Date;
 @EqualsAndHashCode(callSuper = true)
 @Data
 public class UpdateAlarmRecordDTO extends AlarmUrlParam {
+    /**
+     * 报警记录id
+     */
     private String id;
-    private String itemCode;
-    private String projectId;
-    private String objId;
-    private String classCode;
-    private String level;
-    private String remark;
+    /**
+     * 报警名称
+     */
     private String name;
-    private String category;
-    private Integer concern;
+    /**
+     * 备注
+     */
+    private String remark;
+    /**
+     * 报警状态
+     */
     private Integer state;
-    private Date effectStartTime;
-    private Date effectEndTime;
     /**
      * 报警性质
      */
@@ -44,28 +48,28 @@ public class UpdateAlarmRecordDTO extends AlarmUrlParam {
      * 处理状态
      */
     private Integer treatState;
-    private String createUser;
-    private ObjectNode condition;
-    private ObjectNode triggerInfo;
-    private Date triggerTime;
-    private ObjectNode endInfo;
+    /**
+     * 报警恢复时的采集值信息
+     */
+    private JSONObject endInfo;
+    /**
+     * 报警恢复时间
+     */
     private Date endTime;
-    private Date createTime;
-    private String updateUser;
-    private Date updateTime;
-    private Integer valid;
-    private String groupCode;
+    /**
+     * 工单id
+     */
     private String orderId;
+    /**
+     * 工单状态
+     */
     private String orderState;
-    private ObjectNode supplement;
-
     /**
-     * 忽略报警时间
+     * 报警等级
      */
-    private Date ignoreTime;
+    private String level;
     /**
-     * 报警处理完成时间
+     * 补充说明
      */
-    private Date treatEndTime;
-    private String targetId;
+    private JSONObject supplement;
 }

+ 17 - 5
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/vo/AlarmCommentItem.java

@@ -1,6 +1,7 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.vo;
 
 import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
+import lombok.Data;
 
 import java.util.Date;
 
@@ -10,15 +11,26 @@ import java.util.Date;
  * @author lixing
  * @version V1.0 2021/9/16 9:33 上午
  **/
+@Data
 public class AlarmCommentItem {
+    /**
+     * 批注id
+     */
     private String id;
+    /**
+     * 报警记录id
+     */
     private String recordId;
+    /**
+     * 批注内容
+     */
     private String content;
+    /**
+     * 创建人id
+     */
     private String createUser;
+    /**
+     * 创建时间
+     */
     private Date createTime;
-    //	private Date updateTime;
-    //	private String updateUser;
-    //	private Integer valid;
-    private String projectId;
-    private String groupCode;
 }

+ 2 - 0
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/vo/AlarmConfigItem.java

@@ -1,6 +1,7 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.vo;
 
 import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
+import lombok.Data;
 
 /**
  * 报警定义
@@ -8,6 +9,7 @@ import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
  * @author lixing
  * @version V1.0 2021/9/16 9:33 上午
  **/
+@Data
 public class AlarmConfigItem {
     /**
      * 报警定义id

+ 17 - 11
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/vo/AlarmItem.java

@@ -2,6 +2,7 @@ package com.persagy.apm.energyalarmstarter.alarmdata.model.vo;
 
 import com.fasterxml.jackson.databind.node.ObjectNode;
 import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
+import lombok.Data;
 
 import java.util.Date;
 
@@ -11,21 +12,26 @@ import java.util.Date;
  * @author lixing
  * @version V1.0 2021/9/16 9:33 上午
  **/
+@Data
 public class AlarmItem {
+    /**
+     * 条目id
+     */
     private String id;
+    /**
+     * 条目编码
+     */
     private String code;
+    /**
+     * 条目名称
+     */
     private String name;
+    /**
+     * 报警系统
+     */
     private String category;
+    /**
+     * 报警等级
+     */
     private String level;
-    private String remark;
-    private ObjectNode condition;
-    private String dealFun;
-    private String createUser;
-    private Date createTime;
-    private String updateUser;
-    private Date updateTime;
-    private Integer valid;
-    private String projectId;
-    private String groupCode;
-    private String appId;
 }

+ 68 - 16
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/model/vo/AlarmRecordItem.java

@@ -1,7 +1,7 @@
 package com.persagy.apm.energyalarmstarter.alarmdata.model.vo;
 
-import com.fasterxml.jackson.databind.node.ObjectNode;
-import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.AlarmCondition;
+import com.alibaba.fastjson.JSONObject;
+import lombok.Data;
 
 import java.util.Date;
 
@@ -11,19 +11,55 @@ import java.util.Date;
  * @author lixing
  * @version V1.0 2021/9/16 9:33 上午
  **/
+@Data
 public class AlarmRecordItem {
+    /**
+     * 报警记录id
+     */
     private String id;
+    /**
+     * 报警条目编码
+     */
     private String itemCode;
-    private String projectId;
+    /**
+     * 报警对象id
+     */
     private String objId;
+    /**
+     * 设备类编码
+     */
     private String classCode;
+    /**
+     * 报警等级
+     */
     private String level;
+    /**
+     * 项目id
+     */
+    private String projectId;
+    /**
+     * 备注
+     */
     private String remark;
+    /**
+     * 报警名称
+     */
     private String name;
+    /**
+     * 报警系统
+     */
     private String category;
-    private Integer concern;
+    /**
+     * 报警状态
+     */
     private Integer state;
+    /**
+     * 有效期开始时间
+     */
     private Date effectStartTime;
+    /**
+     * 有效期结束时间
+     */
     private Date effectEndTime;
     /**
      * 报警性质
@@ -37,21 +73,38 @@ public class AlarmRecordItem {
      * 处理状态
      */
     private Integer treatState;
-    private String createUser;
-    private ObjectNode condition;
-    private ObjectNode triggerInfo;
+    /**
+     * 报警发生时的报警条件
+     */
+    private JSONObject condition;
+    /**
+     * 报警发生时的采集值信息
+     */
+    private JSONObject triggerInfo;
+    /**
+     * 报警发生时间
+     */
     private Date triggerTime;
-    private ObjectNode endInfo;
+    /**
+     * 报警恢复时的采集值信息
+     */
+    private JSONObject endInfo;
+    /**
+     * 报警恢复时间
+     */
     private Date endTime;
-    private Date createTime;
-    private String updateUser;
-    private Date updateTime;
-    private Integer valid;
-    private String groupCode;
+    /**
+     * 补充说明
+     */
+    private JSONObject supplement;
+    /**
+     * 工单id
+     */
     private String orderId;
+    /**
+     * 工单状态
+     */
     private String orderState;
-    private ObjectNode supplement;
-
     /**
      * 忽略报警时间
      */
@@ -60,5 +113,4 @@ public class AlarmRecordItem {
      * 报警处理完成时间
      */
     private Date treatEndTime;
-    private String targetId;
 }

+ 21 - 3
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/service/AlarmRecordServiceImpl.java

@@ -2,12 +2,13 @@ package com.persagy.apm.energyalarmstarter.alarmdata.service;
 
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
+import com.google.common.collect.Sets;
 import com.persagy.apm.energyalarmstarter.alarmdata.feign.DmpResult;
 import com.persagy.apm.energyalarmstarter.alarmdata.feign.client.AlarmClient;
-import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmconfig.AddAlarmRecordDTO;
-import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmconfig.BatchUpdateAlarmRecordDTO;
-import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmconfig.UpdateAlarmRecordDTO;
+import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord.AddAlarmRecordDTO;
+import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord.BatchUpdateAlarmRecordDTO;
 import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord.QueryAlarmRecordDTO;
+import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.alarmrecord.UpdateAlarmRecordDTO;
 import com.persagy.apm.energyalarmstarter.alarmdata.model.dto.common.QueryDTO;
 import com.persagy.apm.energyalarmstarter.alarmdata.model.vo.AlarmRecordItem;
 import com.persagy.apm.energyalarmstarter.alarmdata.model.vo.DmpBatchUpsertVO;
@@ -18,6 +19,7 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 
 import java.util.List;
+import java.util.Set;
 
 /**
  * 报警记录service类
@@ -40,6 +42,9 @@ public class AlarmRecordServiceImpl {
     public DmpResult<List<AlarmRecordItem>> query(QueryAlarmRecordDTO queryAlarmRecordDTO) throws Exception {
         QueryDTO<QueryAlarmRecordDTO> queryDTO = new QueryDTO<>();
         queryDTO.setCriteria(queryAlarmRecordDTO);
+        // 查询结果中带上忽略时间和处理结束时间
+        Set<String> withColumns = Sets.newHashSet("ignoreTime", "treatEndTime");
+        queryDTO.setWithColumns(withColumns);
         JSONObject jsonObject = Obj2JSONObject.convert(queryDTO);
         DmpResult<JSONArray> result = alarmClient.queryAlarmRecord(queryAlarmRecordDTO.fetchParams(), jsonObject);
         return DmpResultUtil.multiConvert(result, AlarmRecordItem.class);
@@ -81,4 +86,17 @@ public class AlarmRecordServiceImpl {
         return DmpResultUtil.singleConvert(result, DmpBatchUpsertVO.class);
     }
 
+//    public static void main(String[] args) {
+//        AddAlarmRecordDTO addAlarmRecordDTO = new AddAlarmRecordDTO();
+//        JSONObject jsonObject = new JSONObject();
+//        jsonObject.put("any", "sss");
+//        addAlarmRecordDTO.setSupplement(jsonObject);
+//        try {
+//            JSONObject convert = Obj2JSONObject.convert(addAlarmRecordDTO);
+//            System.out.println(convert);
+//        } catch (Exception e) {
+//            e.printStackTrace();
+//        }
+//    }
+
 }

+ 487 - 0
AlarmDataStarter/src/main/java/com/persagy/apm/energyalarmstarter/alarmdata/utils/DateUtils.java

@@ -0,0 +1,487 @@
+package com.persagy.apm.energyalarmstarter.alarmdata.utils;
+
+import com.google.common.collect.Lists;
+
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.time.Instant;
+import java.time.LocalDate;
+import java.time.ZoneId;
+import java.util.*;
+
+public class DateUtils {
+    public static final String SDFSECOND = "yyyyMMddHHmmss";
+    public static final String SDFDAY = "yyyyMMdd";
+    public static final String SDF_SECOND = "yyyy-MM-dd HH:mm:ss";
+    public static final String SDF_SPACE_SECOND = "yyyyMMdd HH:mm:ss";
+    public static final String SDF_DOT_DAY = "yyyy.MM.dd";
+    public static final String SDF_CHAR_MONTH_DAY = "MM月dd日";
+
+    /**
+     * 将pattern格式的字符串日期转换为Date类型日期
+     *
+     * @param source  pattern格式的字符串日期
+     * @param pattern 日期格式如yyyy-MM-dd HH:mm:ss
+     * @return
+     * @throws Exception
+     */
+    public static Date str2Date(String source, String pattern) throws Exception {
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+        return sdf.parse(source);
+    }
+
+    /**
+     * 将Date类型的日期转换成pattern格式的字符串日期
+     *
+     * @param date
+     * @param pattern
+     * @return
+     * @throws Exception
+     */
+    public static String date2Str(Date date, String pattern) {
+        SimpleDateFormat sdf = new SimpleDateFormat(pattern);
+        return sdf.format(date);
+    }
+
+    /**
+     * 获取时间按年偏移offset个单位后的时间
+     *
+     * @param date
+     * @param offset
+     * @return
+     */
+    public static Date getYearOff(Date date, int offset) {
+        return getOffset(date, offset, 5);
+    }
+
+    /**
+     * 获取时间按月偏移offset个单位后的时间
+     *
+     * @param date
+     * @param offset
+     * @return
+     */
+    public static Date getMonthOff(Date date, int offset) {
+        return getOffset(date, offset, 4);
+    }
+
+    /**
+     * 获取时间按周偏移offset个单位后的时间
+     *
+     * @param date
+     * @param offset
+     * @return
+     */
+    public static Date getWeekOff(Date date, int offset) {
+        return getOffset(date, offset, 3);
+    }
+
+    /**
+     * 获取时间按日偏移offset个单位后的时间
+     *
+     * @param date
+     * @param offset
+     * @return
+     */
+    public static Date getDayOff(Date date, int offset) {
+        return getOffset(date, offset, 2);
+    }
+
+    /**
+     * 获取时间按小时偏移offset个单位后的时间
+     *
+     * @param date
+     * @param offset
+     * @return
+     */
+    public static Date getHourOff(Date date, int offset) {
+        return getOffset(date, offset, 1);
+    }
+
+    /**
+     * description 获取时间按分钟偏移offset个单位后的时间
+     *
+     * @param date
+     * @param offset
+     * @return java.util.Date
+     * @author feng
+     * @since 18:51 2018/12/10
+     */
+    public static Date getMinuteOff(Date date, int offset) {
+        return getOffset(date, offset, 0);
+    }
+
+    /**
+     * 获取指定时间粒度偏移量偏移后的时间
+     *
+     * @param date
+     * @param offset int 偏移量
+     * @param type   int 时间粒度0-分,1-时,2-天,3-周,4-月,5-年
+     * @return
+     */
+    private static Date getOffset(Date date, int offset, int type) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+        switch (type) {
+            case 0:
+                cal.add(Calendar.MINUTE, offset);
+                break;
+            case 1:
+                cal.add(Calendar.HOUR_OF_DAY, offset);
+                break;
+            case 2:
+                cal.add(Calendar.DAY_OF_MONTH, offset);
+                break;
+            case 3:
+                cal.add(Calendar.DAY_OF_MONTH, offset * 7);
+                break;
+            case 4:
+                cal.add(Calendar.MONTH, offset);
+                break;
+            case 5:
+                cal.add(Calendar.YEAR, offset);
+                break;
+            default:
+                break;
+        }
+        return cal.getTime();
+    }
+
+    /**
+     * 获取某一天的开始时间 即2017-01-01 00:00:00
+     *
+     * @param date 时间参数
+     * @return
+     * @throws ParseException
+     */
+    public static Date getStartTimeOfDay(Date date) throws ParseException {
+        Calendar c = Calendar.getInstance();
+        c.setTime(date);
+        int year = c.get(Calendar.YEAR);
+        int month = c.get(Calendar.MONTH);
+        int day = c.get(Calendar.DAY_OF_MONTH);
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 0);
+        c.set(Calendar.DAY_OF_MONTH, day);
+        c.set(Calendar.YEAR, year);
+        c.set(Calendar.MONTH, month);
+        return c.getTime();
+    }
+
+    public static Date getFirstDayOfYear(Date date) {
+        Calendar c = Calendar.getInstance();
+        c.setTime(date);
+        int year = c.get(Calendar.YEAR);
+        c.set(Calendar.HOUR_OF_DAY, 0);
+        c.set(Calendar.DAY_OF_MONTH, 1);
+        c.set(Calendar.MINUTE, 0);
+        c.set(Calendar.SECOND, 0);
+        c.set(Calendar.MILLISECOND, 0);
+        c.set(Calendar.YEAR, year);
+        c.set(Calendar.MONTH, 0);
+        return c.getTime();
+    }
+
+    /**
+     * 去年的第一天
+     *
+     * @param date 参照的日期
+     * @return 去年的第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:43 上午
+     */
+    public static Date getFirstDayOfLastYear(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        LocalDate lastYear = localDate.minusYears(1);
+        LocalDate lastYearFirstDay = LocalDate.of(lastYear.getYear(), 1, 1);
+        return Date.from(lastYearFirstDay.atStartOfDay(zoneId).toInstant());
+    }
+
+    /**
+     * 获取两个时间的间隔(ms) endDate - beginDate
+     *
+     * @param beginDate 开始时间
+     * @param endDate   结束时间
+     * @return 相差的时间间隔(ms)
+     * @author lixing
+     * @version V1.0 2021/9/1 10:17 上午
+     */
+    public static Double getDateDurationMs(Date beginDate, Date endDate) {
+        long diff = endDate.getTime() - beginDate.getTime();
+        return (double) diff;
+    }
+
+    public static Double getDateDuration(Date beginDate, Date endDate) {
+        long nh = 1000 * 60 * 60;
+        long diff = endDate.getTime() - beginDate.getTime();
+        return (double) diff / nh;
+    }
+
+    public static Double getDateDuration(long beginTime, long endTime) {
+        long nh = 1000 * 60 * 60;
+        long diff = endTime - beginTime;
+        return (double) diff / nh;
+    }
+
+    public static List<Date> getDayList(Date startDate, Date endDate) throws Exception {
+        List<Date> resultList = new ArrayList<>();
+        while (startDate.before(endDate)) {
+            resultList.add(startDate);
+            startDate = getDayOff(startDate, 1);
+        }
+        return resultList;
+    }
+
+    /**
+     * date转换为localDate
+     *
+     * @param date Date对象
+     * @return LocalDate对象
+     * @author lixing
+     * @version V1.0 2021/6/3 11:36 上午
+     */
+    public static LocalDate convert2LocalDate(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        return instant.atZone(zoneId).toLocalDate();
+    }
+
+    /**
+     * 去年十二月第一天
+     *
+     * @param date 参照的日期
+     * @return 去年十二月第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:43 上午
+     */
+    public static Date getDecemberFirstDayOfLastYear(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        LocalDate lastYear = localDate.minusYears(1);
+        LocalDate lastYearFirstDay = LocalDate.of(lastYear.getYear(), 12, 1);
+        return Date.from(lastYearFirstDay.atStartOfDay(zoneId).toInstant());
+    }
+
+    /**
+     * 给定年份十二月第一天
+     *
+     * @param date 参照的日期
+     * @return 十二月第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:43 上午
+     */
+    public static Date getDecemberFirstDayOfYear(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        LocalDate decemberFirstDayOfYear = LocalDate.of(localDate.getYear(), 12, 1);
+        return Date.from(decemberFirstDayOfYear.atStartOfDay(zoneId).toInstant());
+    }
+
+    /**
+     * 去年同期月份第一天
+     *
+     * @param date 参照的日期
+     * @return 去年同期月份第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:43 上午
+     */
+    public static Date getSameMonthFirstDayOfLastYear(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        LocalDate lastYear = localDate.minusYears(1);
+        LocalDate lastYearFirstDay = LocalDate.of(lastYear.getYear(), lastYear.getMonth(), 1);
+        return Date.from(lastYearFirstDay.atStartOfDay(zoneId).toInstant());
+    }
+
+
+    /**
+     * 获取阶段内的每个月的第一天
+     *
+     * @param startDate 开始日期
+     * @param endDate   结束日期
+     * @return 阶段内的每个月的第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:43 上午
+     */
+    public static List<Date> getFirstDayOfEveryMonth(Date startDate, Date endDate) {
+        if (startDate == null || endDate == null) {
+            return Lists.newArrayList();
+        }
+
+        ZoneId zoneId = ZoneId.systemDefault();
+        LocalDate startLocalDate = startDate.toInstant().atZone(zoneId).toLocalDate();
+        LocalDate endLocalDate = endDate.toInstant().atZone(zoneId).toLocalDate();
+
+        int startYear = startLocalDate.getYear();
+        int startYearMonth = startLocalDate.getMonthValue();
+        int endYear = endLocalDate.getYear();
+        int endYearMonth = endLocalDate.getMonthValue();
+        boolean startYearBigThanEndYear = startYear > endYear;
+        // 同一年,但开始月份大于结束月份
+        boolean startMonthBigThanEndMonth = startYear == endYear && startYearMonth > endYearMonth;
+
+        if (startYearBigThanEndYear || startMonthBigThanEndMonth) {
+            return Lists.newArrayList();
+        }
+
+        List<Date> result = new ArrayList<>();
+        for (int i = startYear; i <= endYear; i++) {
+            int startMonth = 1;
+            int endMonth = 12;
+            if (i == startYear) {
+                startMonth = startYearMonth;
+            }
+            if (i == endYear) {
+                endMonth = endYearMonth;
+            }
+
+            for (int j = startMonth; j <= endMonth; j++) {
+                LocalDate tmp = LocalDate.of(i, j, 1);
+                result.add(Date.from(tmp.atStartOfDay(zoneId).toInstant()));
+            }
+        }
+
+        return result;
+    }
+
+    /**
+     * 给定月份的第一天
+     *
+     * @param date 给定的日期
+     * @return 给定月份的第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:44 上午
+     */
+    public static Date getFirstDayOfMonth(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        LocalDate firstDayOfMonth = LocalDate.of(localDate.getYear(), localDate.getMonth(), 1);
+        return Date.from(firstDayOfMonth.atStartOfDay(zoneId).toInstant());
+    }
+
+    /**
+     * 上个月的第一天
+     *
+     * @param date 参照的日期
+     * @return 上个月的第一天
+     * @author lixing
+     * @version V1.0 2021/5/30 11:44 上午
+     */
+    public static Date getFirstDayOfLastMonth(Date date) {
+        if (date == null) {
+            return null;
+        }
+        Instant instant = date.toInstant();
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate = instant.atZone(zoneId).toLocalDate();
+        LocalDate lastMonth = localDate.minusMonths(1);
+        LocalDate lastMonthFirstDay = LocalDate.of(lastMonth.getYear(), lastMonth.getMonth(), 1);
+        return Date.from(lastMonthFirstDay.atStartOfDay(zoneId).toInstant());
+    }
+
+    /**
+     * 判断日期1是否早于日期2
+     *
+     * @param date1 日期1
+     * @param date2 日期2
+     * @return 判断结果
+     * @author lixing
+     * @version V1.0 2021/5/31 10:44 上午
+     */
+    public static boolean compareDate(Date date1, Date date2) {
+        if (date1 == null) {
+            return false;
+        }
+        if (date2 == null) {
+            return true;
+        }
+        ZoneId zoneId = ZoneId.systemDefault();
+
+        LocalDate localDate1 = date1.toInstant().atZone(zoneId).toLocalDate();
+        LocalDate localDate2 = date2.toInstant().atZone(zoneId).toLocalDate();
+        return localDate1.isBefore(localDate2);
+    }
+
+//    public static void main(String[] args) {
+//
+//        // 2020-02-01
+//        Date startDate = new Date(1580486400000L);
+//        Date endDate = new Date();
+//        System.out.println(getSameMonthFirstDayOfLastYear(startDate));
+//    }
+
+    /**
+     * 打印当前时间距离开始时间的毫秒数
+     *
+     * @param startDate 开始时间
+     * @author lixing
+     * @version V1.0 2021/6/23 7:01 下午
+     */
+    public static void printDuration(Date startDate) {
+        Date now = new Date();
+        System.out.println("用时:" + (now.getTime() - startDate.getTime()));
+    }
+
+    /**
+     * 获取月份内的每一天
+     *
+     * @param month 给定月份
+     * @param pattern 返回值日期格式
+     * @return 月份内的每一天
+     * @author lixing
+     * @version V1.0 2021/9/2 10:28 上午
+     */
+    public static List<String> getDayListOfMonth(Date month, String pattern) {
+        if (month == null) {
+            return null;
+        }
+
+        List<String> list = new ArrayList<>();
+        Calendar aCalendar = Calendar.getInstance(Locale.CHINA);
+        Date firstDayOfMonth = getFirstDayOfMonth(month);
+        aCalendar.setTime(firstDayOfMonth);
+        int day = aCalendar.getActualMaximum(Calendar.DATE);
+
+        for (int i = 1; i <= day; i++) {
+            aCalendar.setTime(getDayOff(firstDayOfMonth, i-1));
+            String dateStr = date2Str(aCalendar.getTime(), pattern);
+            list.add(dateStr);
+        }
+
+        return list;
+
+    }
+}