This is an automated email from the ASF dual-hosted git repository.

leonbao pushed a commit to branch 1.3.6-prepare
in repository https://gitbox.apache.org/repos/asf/incubator-dolphinscheduler.git


The following commit(s) were added to refs/heads/1.3.6-prepare by this push:
     new 7a45dfd  [1.3.6-prepare][API] Improvement the duration field modify 
the display to a time-based minute-second format (e.g. 1d 10h 20m 1s) #4752 
(#4914)
7a45dfd is described below

commit 7a45dfde30e70e46d90fd6f6d4dfd40793bab498
Author: Kirs <[email protected]>
AuthorDate: Tue Mar 9 15:57:51 2021 +0800

    [1.3.6-prepare][API] Improvement the duration field modify the display to a 
time-based minute-second format (e.g. 1d 10h 20m 1s) #4752 (#4914)
    
    * [1.3.6-prepare][API] Improvement the duration field modify the display to 
a time-based minute-second format (e.g. 1d 10h 20m 1s) #4752
    
    * code style
    
    * line separator
---
 .../api/service/ProcessDefinitionService.java      |   2 +-
 .../api/service/ProcessInstanceService.java        |   2 +-
 .../api/service/TaskInstanceService.java           |   2 +-
 .../apache/dolphinscheduler/common/Constants.java  |   4 +
 .../dolphinscheduler/common/utils/DateUtils.java   | 529 ++++++++++++++++++++-
 .../common/utils/DateUtilsTest.java                |  59 ++-
 .../dao/entity/ProcessInstance.java                |   6 +-
 .../dolphinscheduler/dao/entity/TaskInstance.java  |   6 +-
 8 files changed, 598 insertions(+), 12 deletions(-)

diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
index 2312c99..84f7915 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessDefinitionService.java
@@ -1296,7 +1296,7 @@ public class ProcessDefinitionService extends 
BaseDAGService {
         List<ProcessInstance> processInstanceList = 
processInstanceMapper.queryByProcessDefineId(processId, limit);
 
         for (ProcessInstance processInstance:processInstanceList) {
-            
processInstance.setDuration(DateUtils.differSec(processInstance.getStartTime(),processInstance.getEndTime()));
+            
processInstance.setDuration(DateUtils.format2Duration(processInstance.getStartTime(),processInstance.getEndTime()));
         }
 
         if (limit > processInstanceList.size()) {
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java
index b5b5c66..365bb64 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/ProcessInstanceService.java
@@ -184,7 +184,7 @@ public class ProcessInstanceService extends BaseDAGService {
         List<ProcessInstance> processInstances = 
processInstanceList.getRecords();
 
         for(ProcessInstance processInstance: processInstances){
-            
processInstance.setDuration(DateUtils.differSec(processInstance.getStartTime(),processInstance.getEndTime()));
+            
processInstance.setDuration(DateUtils.format2Duration(processInstance.getStartTime(),processInstance.getEndTime()));
             User executor = 
usersService.queryUser(processInstance.getExecutorId());
             if (null != executor) {
                 processInstance.setExecutorName(executor.getUserName());
diff --git 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java
 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java
index 170278e..def1449 100644
--- 
a/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java
+++ 
b/dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/TaskInstanceService.java
@@ -125,7 +125,7 @@ public class TaskInstanceService extends BaseService {
         List<TaskInstance> taskInstanceList = taskInstanceIPage.getRecords();
 
         for(TaskInstance taskInstance : taskInstanceList){
-            
taskInstance.setDuration(DateUtils.differSec(taskInstance.getStartTime(), 
taskInstance.getEndTime()));
+            
taskInstance.setDuration(DateUtils.format2Duration(taskInstance.getStartTime(), 
taskInstance.getEndTime()));
             User executor = 
usersService.queryUser(taskInstance.getExecutorId());
             if (null != executor) {
                 taskInstance.setExecutorName(executor.getUserName());
diff --git 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
index d3faaa2..cc92383 100644
--- 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
+++ 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/Constants.java
@@ -276,6 +276,10 @@ public final class Constants {
     public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";
 
     /**
+     * date format of yyyyMMddHHmmssSSS
+     */
+    public static final String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
+    /**
      * http connect time out
      */
     public static final int HTTP_CONNECT_TIMEOUT = 60 * 1000;
diff --git 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java
 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java
index 1033816..6b88aaf 100644
--- 
a/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java
+++ 
b/dolphinscheduler-common/src/main/java/org/apache/dolphinscheduler/common/utils/DateUtils.java
@@ -1 +1,528 @@
-/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.dolphinscheduler.common.utils;

import org.apache.dolphinscheduler.common.Constants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.time.Instant;
import j
 ava.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
 * date utils
 */
public class DateUtils {

    private static final Logger logger = 
LoggerFactory.getLogger(DateUtils.class);

    /**
     * date to local datetime
     *
     * @param date date
     * @return local datetime
     */
    private static LocalDateTime date2LocalDateTime(Date date) {
        return LocalDateTime.ofInstant(date.toInstant(), 
ZoneId.systemDefault());
    }

    /**
     * local datetime to date
     *
     * @param localDateTime local datetime
     * @return date
     */
    private static Date localDateTime2Date(LocalDateTime localDateTime) {
        Instant instant = 
localDateTime.atZone(ZoneId.systemDefault()).toInstant();
        return Date.from(instant);
    }

    /**
     * get current date str
     *
     * @return date string
     */
    public static String getCurrentTime() {
        return getCurre
 ntTime(Constants.YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * get the date string in the specified format of the current time
     *
     * @param format date format
     * @return date string
     */
    public static String getCurrentTime(String format) {
        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * get the formatted date string
     *
     * @param date date
     * @param format e.g. yyyy-MM-dd HH:mm:ss
     * @return date string
     */
    public static String format(Date date, String format) {
        return format(date2LocalDateTime(date), format);
    }

    /**
     * get the formatted date string
     *
     * @param localDateTime local data time
     * @param format        yyyy-MM-dd HH:mm:ss
     * @return date string
     */
    public static String format(LocalDateTime localDateTime, String format) {
        return localDateTime.format(DateTimeFormatter.ofPattern(format));
    }

    /**
     * convert time to yyy
 y-MM-dd HH:mm:ss format
     *
     * @param date date
     * @return date string
     */
    public static String dateToString(Date date) {
        return format(date, Constants.YYYY_MM_DD_HH_MM_SS);
    }


    /**
     * convert string to date and time
     *
     * @param date date
     * @param format  format
     * @return date
     */
    public static Date parse(String date, String format) {
        try {
            LocalDateTime ldt = LocalDateTime.parse(date, 
DateTimeFormatter.ofPattern(format));
            return localDateTime2Date(ldt);
        } catch (Exception e) {
            logger.error("error while parse date:" + date, e);
        }
        return null;
    }


    /**
     * convert date str to yyyy-MM-dd HH:mm:ss format
     *
     * @param str date string
     * @return yyyy-MM-dd HH:mm:ss format
     */
    public static Date stringToDate(String str) {
        return parse(str, Constants.YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * get seconds between two dat
 es
     *
     * @param d1 date1
     * @param d2 date2
     * @return differ seconds
     */
    public static long differSec(Date d1, Date d2) {
        if(d1 == null || d2 == null){
            return 0;
        }
        return (long) Math.ceil(differMs(d1, d2) / 1000.0);
    }

    /**
     * get ms between two dates
     *
     * @param d1 date1
     * @param d2 date2
     * @return differ ms
     */
    public static long differMs(Date d1, Date d2) {
        return Math.abs(d1.getTime() - d2.getTime());
    }


    /**
     * get hours between two dates
     *
     * @param d1 date1
     * @param d2 date2
     * @return differ hours
     */
    public static long diffHours(Date d1, Date d2) {
        return (long) Math.ceil(diffMin(d1, d2) / 60.0);
    }

    /**
     * get minutes between two dates
     *
     * @param d1 date1
     * @param d2 date2
     * @return differ minutes
     */
    public static long diffMin(Date d1, Date d2) {
        return (long) Math.ceil(diffe
 rSec(d1, d2) / 60.0);
    }


    /**
     * get the date of the specified date in the days before and after
     *
     * @param date date
     * @param day day
     * @return the date of the specified date in the days before and after
     */
    public static Date getSomeDay(Date date, int day) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    /**
     * get the hour of day.
     *
     * @param date date
     * @return hour of day
     */
    public static int getHourIndex(Date date) {
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return calendar.get(Calendar.HOUR_OF_DAY);
    }

    /**
     * compare two dates
     *
     * @param future future date
     * @param old old date
     * @return true if future time greater than old time
     */
    public static boolean compare(Date future, Date old) {
        retu
 rn future.getTime() > old.getTime();
    }

    /**
     * convert schedule string to date
     *
     * @param schedule schedule
     * @return convert schedule string to date
     */
    public static Date getScheduleDate(String schedule) {
        return stringToDate(schedule);
    }

    /**
     * format time to readable
     *
     * @param ms ms
     * @return format time
     */
    public static String format2Readable(long ms) {

        long days = ms / (1000 * 60 * 60 * 24);
        long hours = (ms % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60);
        long minutes = (ms % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (ms % (1000 * 60)) / 1000;

        return String.format("%02d %02d:%02d:%02d", days, hours, minutes, 
seconds);

    }

    /**
     * get monday
     *
     * note: Set the first day of the week to Monday, the default is Sunday
     * @param date date
     * @return get monday
     */
    public static Date getMonday(Date date) {
        Calendar c
 al = Calendar.getInstance();

        cal.setTime(date);

        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);

        return cal.getTime();
    }

    /**
     * get sunday
     *
     * note: Set the first day of the week to Monday, the default is Sunday
     * @param date date
     * @return get sunday
     */
    public static Date getSunday(Date date) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);

        cal.setFirstDayOfWeek(Calendar.MONDAY);
        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);

        return cal.getTime();
    }

    /**
     * get first day of month
     *
     * @param date date
     * @return first day of month
     * */
    public static Date getFirstDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();

        cal.setTime(date);
        cal.set(Calendar.DAY_OF_MONTH, 1);

        return cal.getTime();
    }

    /**
     * get some hour of day
     *
      * @param date date
     * @param offsetHour hours
     * @return some hour of day
     * */
    public static Date getSomeHourOfDay(Date date, int offsetHour) {
        Calendar cal = Calendar.getInstance();

        cal.setTime(date);
        cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + 
offsetHour);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);

        return cal.getTime();
    }

    /**
     * get last day of month
     *
     * @param  date date
     * @return  get last day of month
     */
    public static Date getLastDayOfMonth(Date date) {
        Calendar cal = Calendar.getInstance();

        cal.setTime(date);

        cal.add(Calendar.MONTH, 1);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        cal.add(Calendar.DAY_OF_MONTH, -1);

        return cal.getTime();
    }

    /**
     * return YYYY-MM-DD 00:00:00
     *
     * @param inputDay date
     * @return start day
     */
   
  public static Date getStartOfDay(Date inputDay) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(inputDay);
        cal.set(Calendar.HOUR_OF_DAY, 0);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * return YYYY-MM-DD 23:59:59
     *
     * @param inputDay day
     * @return end of day
     */
    public static Date getEndOfDay(Date inputDay) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(inputDay);
        cal.set(Calendar.HOUR_OF_DAY, 23);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * return YYYY-MM-DD 00:00:00
     *
     * @param inputDay day
     * @return start of hour
     */
    public static Date getStartOfHour(Date inputDay) {
        Calendar cal = Calendar.getInstance();
        cal.setTim
 e(inputDay);
        cal.set(Calendar.MINUTE, 0);
        cal.set(Calendar.SECOND, 0);
        cal.set(Calendar.MILLISECOND, 0);
        return cal.getTime();
    }

    /**
     * return YYYY-MM-DD 23:59:59
     *
     * @param inputDay day
     * @return end of hour
     */
    public static Date getEndOfHour(Date inputDay) {
        Calendar cal = Calendar.getInstance();
        cal.setTime(inputDay);
        cal.set(Calendar.MINUTE, 59);
        cal.set(Calendar.SECOND, 59);
        cal.set(Calendar.MILLISECOND, 999);
        return cal.getTime();
    }

    /**
     * get current date
     * @return current date
     */
    public static Date getCurrentDate() {
        return DateUtils.parse(DateUtils.getCurrentTime(),
                Constants.YYYY_MM_DD_HH_MM_SS);
    }

    /**
     * get date
     * @param date date
     * @param calendarField calendarField
     * @param amount amount
     * @return date
     */
    public static Date add(final Date date, final int calendar
 Field, final int amount) {
        if (date == null) {
            throw new IllegalArgumentException("The date must not be null");
        }
        final Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(calendarField, amount);
        return c.getTime();
    }
}
\ No newline at end of file
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.common.utils;
+
+import org.apache.dolphinscheduler.common.Constants;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
+import java.util.Calendar;
+import java.util.Date;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * date utils
+ */
+public class DateUtils {
+
+    private static final Logger logger = 
LoggerFactory.getLogger(DateUtils.class);
+
+    private DateUtils() {
+        throw new UnsupportedOperationException("Construct DateUtils");
+    }
+
+    /**
+     * date to local datetime
+     *
+     * @param date date
+     * @return local datetime
+     */
+    private static LocalDateTime date2LocalDateTime(Date date) {
+        return LocalDateTime.ofInstant(date.toInstant(), 
ZoneId.systemDefault());
+    }
+
+    /**
+     * local datetime to date
+     *
+     * @param localDateTime local datetime
+     * @return date
+     */
+    private static Date localDateTime2Date(LocalDateTime localDateTime) {
+        Instant instant = 
localDateTime.atZone(ZoneId.systemDefault()).toInstant();
+        return Date.from(instant);
+    }
+
+    /**
+     * get current date str
+     *
+     * @return date string
+     */
+    public static String getCurrentTime() {
+        return getCurrentTime(Constants.YYYY_MM_DD_HH_MM_SS);
+    }
+
+    /**
+     * get the date string in the specified format of the current time
+     *
+     * @param format date format
+     * @return date string
+     */
+    public static String getCurrentTime(String format) {
+        return LocalDateTime.now().format(DateTimeFormatter.ofPattern(format));
+    }
+
+    /**
+     * get the formatted date string
+     *
+     * @param date date
+     * @param format e.g. yyyy-MM-dd HH:mm:ss
+     * @return date string
+     */
+    public static String format(Date date, String format) {
+        return format(date2LocalDateTime(date), format);
+    }
+
+    /**
+     * get the formatted date string
+     *
+     * @param localDateTime local data time
+     * @param format yyyy-MM-dd HH:mm:ss
+     * @return date string
+     */
+    public static String format(LocalDateTime localDateTime, String format) {
+        return localDateTime.format(DateTimeFormatter.ofPattern(format));
+    }
+
+    /**
+     * convert time to yyyy-MM-dd HH:mm:ss format
+     *
+     * @param date date
+     * @return date string
+     */
+    public static String dateToString(Date date) {
+        return format(date, Constants.YYYY_MM_DD_HH_MM_SS);
+    }
+
+
+    /**
+     * convert string to date and time
+     *
+     * @param date date
+     * @param format format
+     * @return date
+     */
+    public static Date parse(String date, String format) {
+        try {
+            LocalDateTime ldt = LocalDateTime.parse(date, 
DateTimeFormatter.ofPattern(format));
+            return localDateTime2Date(ldt);
+        } catch (Exception e) {
+            logger.error("error while parse date:" + date, e);
+        }
+        return null;
+    }
+
+
+    /**
+     * convert date str to yyyy-MM-dd HH:mm:ss format
+     *
+     * @param str date string
+     * @return yyyy-MM-dd HH:mm:ss format
+     */
+    public static Date stringToDate(String str) {
+        return parse(str, Constants.YYYY_MM_DD_HH_MM_SS);
+    }
+
+    /**
+     * get seconds between two dates
+     *
+     * @param d1 date1
+     * @param d2 date2
+     * @return differ seconds
+     */
+    public static long differSec(Date d1, Date d2) {
+        if (d1 == null || d2 == null) {
+            return 0;
+        }
+        return (long) Math.ceil(differMs(d1, d2) / 1000.0);
+    }
+
+    /**
+     * get ms between two dates
+     *
+     * @param d1 date1
+     * @param d2 date2
+     * @return differ ms
+     */
+    public static long differMs(Date d1, Date d2) {
+        return Math.abs(d1.getTime() - d2.getTime());
+    }
+
+
+    /**
+     * get hours between two dates
+     *
+     * @param d1 date1
+     * @param d2 date2
+     * @return differ hours
+     */
+    public static long diffHours(Date d1, Date d2) {
+        return (long) Math.ceil(diffMin(d1, d2) / 60.0);
+    }
+
+    /**
+     * get minutes between two dates
+     *
+     * @param d1 date1
+     * @param d2 date2
+     * @return differ minutes
+     */
+    public static long diffMin(Date d1, Date d2) {
+        return (long) Math.ceil(differSec(d1, d2) / 60.0);
+    }
+
+
+    /**
+     * get the date of the specified date in the days before and after
+     *
+     * @param date date
+     * @param day day
+     * @return the date of the specified date in the days before and after
+     */
+    public static Date getSomeDay(Date date, int day) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        calendar.add(Calendar.DATE, day);
+        return calendar.getTime();
+    }
+
+    /**
+     * get the hour of day.
+     *
+     * @param date date
+     * @return hour of day
+     */
+    public static int getHourIndex(Date date) {
+        Calendar calendar = Calendar.getInstance();
+        calendar.setTime(date);
+        return calendar.get(Calendar.HOUR_OF_DAY);
+    }
+
+    /**
+     * compare two dates
+     *
+     * @param future future date
+     * @param old old date
+     * @return true if future time greater than old time
+     */
+    public static boolean compare(Date future, Date old) {
+        return future.getTime() > old.getTime();
+    }
+
+    /**
+     * convert schedule string to date
+     *
+     * @param schedule schedule
+     * @return convert schedule string to date
+     */
+    public static Date getScheduleDate(String schedule) {
+        return stringToDate(schedule);
+    }
+
+    /**
+     * format time to readable
+     *
+     * @param ms ms
+     * @return format time
+     */
+    public static String format2Readable(long ms) {
+
+        long days = MILLISECONDS.toDays(ms);
+        long hours = MILLISECONDS.toDurationHours(ms);
+        long minutes = MILLISECONDS.toDurationMinutes(ms);
+        long seconds = MILLISECONDS.toDurationSeconds(ms);
+
+        return String.format("%02d %02d:%02d:%02d", days, hours, minutes, 
seconds);
+
+    }
+
+    /**
+     * format time to duration
+     *
+     * @param d1 d1
+     * @param d2 d2
+     * @return format time
+     */
+    public static String format2Duration(Date d1, Date d2) {
+        if (d1 == null || d2 == null) {
+            return null;
+        }
+        return format2Duration(differMs(d1, d2));
+    }
+
+    /**
+     * format time to duration
+     *
+     * @param ms ms
+     * @return format time
+     */
+    public static String format2Duration(long ms) {
+
+        long days = MILLISECONDS.toDays(ms);
+        long hours = MILLISECONDS.toDurationHours(ms);
+        long minutes = MILLISECONDS.toDurationMinutes(ms);
+        long seconds = MILLISECONDS.toDurationSeconds(ms);
+
+        StringBuilder strBuilder = new StringBuilder();
+        strBuilder = days > 0 ? strBuilder.append(days).append("d").append(" 
") : strBuilder;
+        strBuilder = hours > 0 ? strBuilder.append(hours).append("h").append(" 
") : strBuilder;
+        strBuilder = minutes > 0 ? 
strBuilder.append(minutes).append("m").append(" ") : strBuilder;
+        strBuilder = seconds > 0 ? strBuilder.append(seconds).append("s") : 
strBuilder;
+
+        return strBuilder.toString();
+
+    }
+
+    /**
+     * get monday
+     * <p>
+     * note: Set the first day of the week to Monday, the default is Sunday
+     *
+     * @param date date
+     * @return get monday
+     */
+    public static Date getMonday(Date date) {
+        Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+
+        cal.setFirstDayOfWeek(Calendar.MONDAY);
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
+
+        return cal.getTime();
+    }
+
+    /**
+     * get sunday
+     * <p>
+     * note: Set the first day of the week to Monday, the default is Sunday
+     *
+     * @param date date
+     * @return get sunday
+     */
+    public static Date getSunday(Date date) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(date);
+
+        cal.setFirstDayOfWeek(Calendar.MONDAY);
+        cal.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
+
+        return cal.getTime();
+    }
+
+    /**
+     * get first day of month
+     *
+     * @param date date
+     * @return first day of month
+     */
+    public static Date getFirstDayOfMonth(Date date) {
+        Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+
+        return cal.getTime();
+    }
+
+    /**
+     * get some hour of day
+     *
+     * @param date date
+     * @param offsetHour hours
+     * @return some hour of day
+     */
+    public static Date getSomeHourOfDay(Date date, int offsetHour) {
+        Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+        cal.set(Calendar.HOUR_OF_DAY, cal.get(Calendar.HOUR_OF_DAY) + 
offsetHour);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+
+        return cal.getTime();
+    }
+
+    /**
+     * get last day of month
+     *
+     * @param date date
+     * @return get last day of month
+     */
+    public static Date getLastDayOfMonth(Date date) {
+        Calendar cal = Calendar.getInstance();
+
+        cal.setTime(date);
+
+        cal.add(Calendar.MONTH, 1);
+        cal.set(Calendar.DAY_OF_MONTH, 1);
+        cal.add(Calendar.DAY_OF_MONTH, -1);
+
+        return cal.getTime();
+    }
+
+    /**
+     * return YYYY-MM-DD 00:00:00
+     *
+     * @param inputDay date
+     * @return start day
+     */
+    public static Date getStartOfDay(Date inputDay) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(inputDay);
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * return YYYY-MM-DD 23:59:59
+     *
+     * @param inputDay day
+     * @return end of day
+     */
+    public static Date getEndOfDay(Date inputDay) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(inputDay);
+        cal.set(Calendar.HOUR_OF_DAY, 23);
+        cal.set(Calendar.MINUTE, 59);
+        cal.set(Calendar.SECOND, 59);
+        cal.set(Calendar.MILLISECOND, 999);
+        return cal.getTime();
+    }
+
+    /**
+     * return YYYY-MM-DD 00:00:00
+     *
+     * @param inputDay day
+     * @return start of hour
+     */
+    public static Date getStartOfHour(Date inputDay) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(inputDay);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        return cal.getTime();
+    }
+
+    /**
+     * return YYYY-MM-DD 23:59:59
+     *
+     * @param inputDay day
+     * @return end of hour
+     */
+    public static Date getEndOfHour(Date inputDay) {
+        Calendar cal = Calendar.getInstance();
+        cal.setTime(inputDay);
+        cal.set(Calendar.MINUTE, 59);
+        cal.set(Calendar.SECOND, 59);
+        cal.set(Calendar.MILLISECOND, 999);
+        return cal.getTime();
+    }
+
+    /**
+     * get current date
+     *
+     * @return current date
+     */
+    public static Date getCurrentDate() {
+        return DateUtils.parse(DateUtils.getCurrentTime(),
+                Constants.YYYY_MM_DD_HH_MM_SS);
+    }
+
+    /**
+     * get date
+     *
+     * @param date date
+     * @param calendarField calendarField
+     * @param amount amount
+     * @return date
+     */
+    public static Date add(final Date date, final int calendarField, final int 
amount) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        final Calendar c = Calendar.getInstance();
+        c.setTime(date);
+        c.add(calendarField, amount);
+        return c.getTime();
+    }
+
+    /**
+     * get current time stamp : yyyyMMddHHmmssSSS
+     *
+     * @return date string
+     */
+    public static String getCurrentTimeStamp() {
+        return getCurrentTime(Constants.YYYYMMDDHHMMSSSSS);
+    }
+
+    static final long C0 = 1L;
+    static final long C1 = C0 * 1000L;
+    static final long C2 = C1 * 1000L;
+    static final long C3 = C2 * 1000L;
+    static final long C4 = C3 * 60L;
+    static final long C5 = C4 * 60L;
+    static final long C6 = C5 * 24L;
+
+    /**
+     * Time unit representing one thousandth of a second
+     */
+    public static class MILLISECONDS {
+
+        public static long toSeconds(long d) {
+            return d / (C3 / C2);
+        }
+
+        public static long toMinutes(long d) {
+            return d / (C4 / C2);
+        }
+
+        public static long toHours(long d) {
+            return d / (C5 / C2);
+        }
+
+        public static long toDays(long d) {
+            return d / (C6 / C2);
+        }
+
+        public static long toDurationSeconds(long d) {
+            return (d % (C4 / C2)) / (C3 / C2);
+        }
+
+        public static long toDurationMinutes(long d) {
+            return (d % (C5 / C2)) / (C4 / C2);
+        }
+
+        public static long toDurationHours(long d) {
+            return (d % (C6 / C2)) / (C5 / C2);
+        }
+
+    }
+
+}
diff --git 
a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java
 
b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java
index 6800f6b..e9be6f4 100644
--- 
a/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java
+++ 
b/dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/DateUtilsTest.java
@@ -16,12 +16,13 @@
  */
 package org.apache.dolphinscheduler.common.utils;
 
-import org.junit.Assert;
-import org.junit.Test;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
 
+import org.junit.Assert;
+import org.junit.Test;
+
 public class DateUtilsTest {
     @Test
     public void format2Readable() throws ParseException {
@@ -150,4 +151,58 @@ public class DateUtilsTest {
         Date curr = DateUtils.getEndOfHour(d1);
         Assert.assertEquals(DateUtils.dateToString(curr), "2019-01-31 
11:59:59");
     }
+
+    @Test
+    public void getCurrentTimeStamp() {
+        String timeStamp = DateUtils.getCurrentTimeStamp();
+        Assert.assertNotNull(timeStamp);
+    }
+
+    @Test
+    public void testFormat2Duration() {
+
+        // days hours minutes seconds
+        Date d1 = DateUtils.stringToDate("2020-01-20 11:00:00");
+        Date d2 = DateUtils.stringToDate("2020-01-21 12:10:10");
+        String duration = DateUtils.format2Duration(d2, d1);
+        Assert.assertEquals("1d 1h 10m 10s", duration);
+
+        // hours minutes seconds
+        d1 = DateUtils.stringToDate("2020-01-20 11:00:00");
+        d2 = DateUtils.stringToDate("2020-01-20 12:10:10");
+        duration = DateUtils.format2Duration(d2, d1);
+        Assert.assertEquals("1h 10m 10s", duration);
+
+        // minutes seconds
+        d1 = DateUtils.stringToDate("2020-01-20 11:00:00");
+        d2 = DateUtils.stringToDate("2020-01-20 11:10:10");
+        duration = DateUtils.format2Duration(d2, d1);
+        Assert.assertEquals("10m 10s", duration);
+
+        // minutes seconds
+        d1 = DateUtils.stringToDate("2020-01-20 11:10:00");
+        d2 = DateUtils.stringToDate("2020-01-20 11:10:10");
+        duration = DateUtils.format2Duration(d2, d1);
+        Assert.assertEquals("10s", duration);
+
+        d1 = DateUtils.stringToDate("2020-01-20 11:10:00");
+        d2 = DateUtils.stringToDate("2020-01-21 11:10:10");
+        duration = DateUtils.format2Duration(d2, d1);
+        Assert.assertEquals("1d 10s", duration);
+
+        d1 = DateUtils.stringToDate("2020-01-20 11:10:00");
+        d2 = DateUtils.stringToDate("2020-01-20 16:10:10");
+        duration = DateUtils.format2Duration(d2, d1);
+        Assert.assertEquals("5h 10s", duration);
+
+    }
+
+    @Test
+    public void testNullDuration() {
+        // days hours minutes seconds
+        Date d1 = DateUtils.stringToDate("2020-01-20 11:00:00");
+        Date d2 = null;
+        Assert.assertNull(DateUtils.format2Duration(d1, d2));
+    }
+
 }
diff --git 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
index 2fa8e64..8e95ebe 100644
--- 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
+++ 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/ProcessInstance.java
@@ -187,7 +187,7 @@ public class ProcessInstance {
      * @return
      */
     @TableField(exist = false)
-    private Long duration;
+    private String duration;
 
     /**
      * process instance priority
@@ -527,11 +527,11 @@ public class ProcessInstance {
         this.dependenceScheduleTimes = dependenceScheduleTimes;
     }
 
-    public Long getDuration() {
+    public String getDuration() {
         return duration;
     }
 
-    public void setDuration(Long duration) {
+    public void setDuration(String duration) {
         this.duration = duration;
     }
 
diff --git 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/TaskInstance.java
 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/TaskInstance.java
index 5a6aa49..29c5232 100644
--- 
a/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/TaskInstance.java
+++ 
b/dolphinscheduler-dao/src/main/java/org/apache/dolphinscheduler/dao/entity/TaskInstance.java
@@ -160,7 +160,7 @@ public class TaskInstance implements Serializable {
      * duration
      */
     @TableField(exist = false)
-    private Long duration;
+    private String duration;
 
     /**
      * max retry times
@@ -403,11 +403,11 @@ public class TaskInstance implements Serializable {
         this.processInstanceName = processInstanceName;
     }
 
-    public Long getDuration() {
+    public String getDuration() {
         return duration;
     }
 
-    public void setDuration(Long duration) {
+    public void setDuration(String duration) {
         this.duration = duration;
     }
 

Reply via email to