ITPub博客

首页 > 数据库 > 数据库开发技术 > java时间表达式工具类

java时间表达式工具类

原创 数据库开发技术 作者:毛毛小妖的笔记 时间:2023-03-29 19:30:00 0 删除 编辑

今天分享一个java中时间表达式的工具类,话不多说,直接上代码。以下代码是可以直接运行的。

一、定义常量类

package com.eyesmoons.date;

public class Constants
{
   public static final String NEWLINE = "\n";
   public static final String COMMA = ",";
   public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";
   public static final String YYYYMMDDHHMMSSSSS = "yyyyMMddHHmmssSSS";
   public static final String MONTH_BEGIN = "month_begin";
   public static final String ADD_YEARS = "add_years";
   public static final String ADD_MONTHS = "add_months";
   public static final String MONTH_END = "month_end";
   public static final String WEEK_BEGIN = "week_begin";
   public static final String WEEK_END = "week_end";
   public static final char SUBTRACT_CHAR = '-';
   public static final char ADD_CHAR = '+';
   public static final char MULTIPLY_CHAR = '*';
   public static final char DIVISION_CHAR = '/';
   public static final char LEFT_BRACE_CHAR = '(';
   public static final char RIGHT_BRACE_CHAR = ')';
   public static final String ADD_STRING = "+";
   public static final String MULTIPLY_STRING = "*";
   public static final String DIVISION_STRING = "/";
   public static final String LEFT_BRACE_STRING = "(";
   public static final char P = 'P';
   public static final char N = 'N';
   public static final String SUBTRACT_STRING = "-";
   public static final String YEAR_END = "year_end";
   public static final String QUARTER_BEGIN = "quarter_begin";
   public static final String QUARTER_END = "quarter_end";
}

二、自定义时间工具类

package com.eyesmoons.date;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.apache.commons.lang3.time.DateUtils;

import java.lang.management.ManagementFactory;
import java.sql.Timestamp;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.Calendar;
import java.util.Date;

/**
* 时间工具类
*/
@Slf4j
public class CustomDateUtil extends DateUtils
{
   public static String YYYY_MM_DD = "yyyy-MM-dd";

   public static String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

   public static String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

   private static String[] parsePatterns = {
           "yyyy-MM-dd", "yyyy-MM-dd HH:mm:ss", "yyyy-MM-dd HH:mm", "yyyy-MM",
           "yyyy/MM/dd", "yyyy/MM/dd HH:mm:ss", "yyyy/MM/dd HH:mm", "yyyy/MM",
           "yyyy.MM.dd", "yyyy.MM.dd HH:mm:ss", "yyyy.MM.dd HH:mm", "yyyy.MM"};

   /**
    * 获取当前Date型日期
    *
    * @return Date() 当前日期
    */
   public static Date getNowDate()
  {
       return new Date();
  }

   /**
    * 获取当前日期, 默认格式为yyyy-MM-dd
    */
   public static String getDate()
  {
       return dateTimeNow(YYYY_MM_DD);
  }

   public static final String getTime()
  {
       return dateTimeNow(YYYY_MM_DD_HH_MM_SS);
  }

   public static final String dateTimeNow()
  {
       return dateTimeNow(YYYYMMDDHHMMSS);
  }

   public static final String dateTimeNow(final String format)
  {
       return parseDateToStr(format, new Date());
  }

   public static final String dateTime(final Date date)
  {
       return parseDateToStr(YYYY_MM_DD, date);
  }

   public static final String dateTime(final String format, final Date date)
  {
       return parseDateToStr(format, date);
  }

   public static final String parseDateToStr(final String format, final Date date)
  {
       return new SimpleDateFormat(format).format(date);
  }

   public static final Date dateTime(final String format, final String ts)
  {
       try
      {
           return new SimpleDateFormat(format).parse(ts);
      }
       catch (ParseException e)
      {
           throw new RuntimeException(e);
      }
  }

   /**
    * 日期路径 即年/月/日 如2018/08/08
    */
   public static final String datePath()
  {
       Date now = new Date();
       return DateFormatUtils.format(now, "yyyy/MM/dd");
  }

   /**
    * 日期路径 即年/月/日 如20180808
    */
   public static final String dateTime()
  {
       Date now = new Date();
       return DateFormatUtils.format(now, "yyyyMMdd");
  }

   /**
    * 日期型字符串转化为日期 格式
    */
   public static Date parseDate(Object str)
  {
       if (str == null)
      {
           return null;
      }
       try
      {
           return parseDate(str.toString(), parsePatterns);
      }
       catch (ParseException e)
      {
           return null;
      }
  }
   
   /**
    * 获取服务器启动时间
    */
   public static Date getServerStartDate()
  {
       long time = ManagementFactory.getRuntimeMXBean().getStartTime();
       return new Date(time);
  }

   /**
    * 计算两个时间差
    */
   public static String getDatePoor(Date endDate, Date nowDate)
  {
       long nd = 1000 * 24 * 60 * 60;
       long nh = 1000 * 60 * 60;
       long nm = 1000 * 60;
       // long ns = 1000;
       // 获得两个时间的毫秒时间差异
       long diff = endDate.getTime() - nowDate.getTime();
       // 计算差多少天
       long day = diff / nd;
       // 计算差多少小时
       long hour = diff % nd / nh;
       // 计算差多少分钟
       long min = diff % nd % nh / nm;
       // 计算差多少秒//输出结果
       // long sec = diff % nd % nh % nm / ns;
       return day + "天" + hour + "小时" + min + "分钟";
  }

   /**
    * 将数字转换成时分秒,
    * 例如: 5261 -> 5秒261毫秒, 3602118 -> 1小时2秒118毫秒
    * @param n 数字
    */
   public static String convertNumber2DateString(Long n) {
       String result = "";
       long hh = n / 3600000;
       long mm = (n - hh * 3600000) / 60000;
       long ss = (n - hh * 3600000 - mm * 60000) / 1000;
       long ms = (n - hh * 3600000 - mm * 60000 - ss * 1000);

       if (n > 0) {
           if (hh > 0) {
               result += hh + "小时";
          }
           if (mm > 0) {
               result += mm + "分";
          }
           if (ss > 0) {
               result += ss + "秒";
          }
           if (ms > 0) {
               result += ms + "毫秒";
          }
      } else {
           result = "NaN";
      }
       return result;
  }

   /**
    * 计算两个日期相差天数
    */
   public static int getDatePoorDay(Date endDate, Date startDate)
  {
       // 获得两个时间的毫秒时间差异
       long diff = endDate.getTime() - startDate.getTime();
       // 计算差多少天
       int day =(int) (diff / (1000 * 24 * 60 * 60));
       return day;
  }

   /**
    * 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) {
           log.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);
  }

   public static Date StringToDate(String dateString, String pattern) {
       SimpleDateFormat dateFormat = new SimpleDateFormat(pattern); // 设置日期格式
       try {
           return dateFormat.parse(dateString);
      } catch (ParseException e) {
           e.printStackTrace();
      }
       return null;
  }

   /**
    * 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
    * 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();
  }

   public static Date getLastDayOfYear(Date date) {
       Calendar cal = Calendar.getInstance();
       cal.setTime(date);
       cal.add(Calendar.YEAR, 1);
       cal.set(Calendar.DAY_OF_YEAR, 1);
       cal.add(Calendar.DAY_OF_YEAR, -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 CustomDateUtil.parse(CustomDateUtil.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);
  }

   /**
    *
    * @param format
    * @param timestamp 秒级
    * @return
    */
   public static Long getTimeStamp(final String format, Long timestamp) {
       String dateString = dateTime(format, new Timestamp(timestamp*1000));
       Date fullDate = dateTime(format, dateString);
       String realDateString = dateTime(YYYY_MM_DD_HH_MM_SS, fullDate);
       return Timestamp.valueOf(realDateString).getTime()/1000;
  }


   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;

   public static Date getQuarterBegin(Date date) {
       Calendar calendar = Calendar.getInstance();
       calendar.setTime(date);

       int year = calendar.get(Calendar.YEAR);
       int month = calendar.get(Calendar.MONTH);
       // 计算季度
       int quarter = (int) Math.ceil((month + 1) / 3.0);
       // 计算季度第一个月
       int firstMonthOfQuarter = (quarter - 1) * 3;
       // 设置日期为季度第一个月的第一天
       calendar.set(year, firstMonthOfQuarter, 1);
       return calendar.getTime();
  }

   public static Date getQuarterEnd(Date date) {
       Calendar calendar = Calendar.getInstance();
       calendar.setTime(date);

       int year = calendar.get(Calendar.YEAR);
       int month = calendar.get(Calendar.MONTH);

       // 计算季度
       int quarter = (int) Math.ceil((month + 1) / 3.0);
       // 计算季度最后一个月
       int lastMonthOfQuarter = quarter * 3 - 1;
       // 设置日期为季度最后一个月的第一天
       calendar.set(year, lastMonthOfQuarter, 1);
       // 获取季度最后一个月的最大天数
       int lastDay = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
       // 将日期设置为季度最后一天
       calendar.set(Calendar.DAY_OF_MONTH, lastDay);
       return calendar.getTime();
  }

   /**
    * 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);
      }

  }

   public static String timeStrBeforeNow(int hours) {
       DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:dd");
       LocalDateTime timeNow = LocalDateTime.now();
       LocalDateTime localDate = timeNow.minusHours(hours);
       String startTime  = localDate.format(fmt);
       return startTime;
  }

   public static String dateStrBeforeNow(int months) {
       DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd");
       LocalDate endDate = LocalDate.now();
       LocalDate localDate = endDate.minusMonths(months).plusDays(1);
       String startTime  = localDate.format(fmt);
       return startTime;
  }

   /**
    * 时间戳转日期时间
    * @param timeStamp
    * @param format
    * @return
    */
   public static String stampToDateTime(Long timeStamp, String format) {
       SimpleDateFormat dateFormat = new SimpleDateFormat(format);
       Date date = new Date(timeStamp);
       return dateFormat.format(date);
  }
}

三、时间表达式工具类

package com.eyesmoons.date;

import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.util.PropertyPlaceholderHelper;
import java.util.*;
import static com.eyesmoons.date.Constants.*;

/**
* time placeholder util
*/
@Slf4j
public class TimePlaceholderUtils {
   /**
    * Prefix of the position to be replaced
    */
   public static final String PLACEHOLDER_PREFIX = "$[";

   /**
    * suffix of the position to be replaced
    */
   public static final String PLACEHOLDER_SUFFIX = "]";

   /**
    * Replaces all placeholders of format {@code ${name}} with the value returned
    * from the supplied {@link PropertyPlaceholderHelper.PlaceholderResolver}.
    *
    * @param value                         the value containing the placeholders to be replaced
    * @param date                           custom date
    * @param ignoreUnresolvablePlaceholders ignore unresolvable placeholders
    * @return the supplied value with placeholders replaced inline
    */
   public static String replacePlaceholders(String value, Date date, boolean ignoreUnresolvablePlaceholders) {
       PropertyPlaceholderHelper strictHelper = getPropertyPlaceholderHelper(false);
       PropertyPlaceholderHelper nonStrictHelper = getPropertyPlaceholderHelper(true);
       PropertyPlaceholderHelper helper = (ignoreUnresolvablePlaceholders ? nonStrictHelper : strictHelper);
       return helper.replacePlaceholders(value, new TimePlaceholderResolver(value, date));
  }

   /**
    * Creates a new {@code PropertyPlaceholderHelper} that uses the supplied prefix and suffix.
    *
    * @param ignoreUnresolvablePlaceholders indicates whether unresolvable placeholders should
    *                                       be ignored ({@code true}) or cause an exception ({@code false})
    */
   private static PropertyPlaceholderHelper getPropertyPlaceholderHelper(boolean ignoreUnresolvablePlaceholders) {
       return new PropertyPlaceholderHelper(PLACEHOLDER_PREFIX, PLACEHOLDER_SUFFIX, null, ignoreUnresolvablePlaceholders);
  }

   /**
    * calculate expression's value
    *
    * @param expression expression
    * @return expression's value
    */
   public static Integer calculate(String expression) {
       expression = StringUtils.trim(expression);
       expression = convert(expression);
       List<String> result = string2List(expression);
       result = convert2SuffixList(result);

       return calculate(result);
  }

   /**
    * Change the sign in the expression to P (positive) N (negative)
    * @param expression 表达式
    * @return eg. "-3+-6*(+8)-(-5) -> S3+S6*(P8)-(S5)"
    */
   private static String convert(String expression) {
       char[] arr = expression.toCharArray();
       for (int i = 0; i < arr.length; i++) {
           if (arr[i] == SUBTRACT_CHAR) {
               if (i == 0) {
                   arr[i] = N;
              } else {
                   char c = arr[i - 1];
                   if (c == ADD_CHAR || c == SUBTRACT_CHAR || c == MULTIPLY_CHAR || c == DIVISION_CHAR || c == LEFT_BRACE_CHAR) {
                       arr[i] = N;
                  }
              }
          } else if (arr[i] == ADD_CHAR) {
               if (i == 0) {
                   arr[i] = P;
              } else {
                   char c = arr[i - 1];
                   if (c == ADD_CHAR || c == SUBTRACT_CHAR || c == MULTIPLY_CHAR || c == DIVISION_CHAR || c == LEFT_BRACE_CHAR) {
                       arr[i] = P;
                  }
              }
          }
      }
       return new String(arr);
  }

   /**
    * to suffix expression
    */
   private static List<String> convert2SuffixList(List<String> srcList) {
       List<String> result = new ArrayList<>();
       Stack<String> stack = new Stack<>();

       for (String s : srcList) {
           if (Character.isDigit(s.charAt(0))) {
               result.add(s);
          } else {
               switch (s.charAt(0)) {
                   case LEFT_BRACE_CHAR:
                       stack.push(s);
                       break;
                   case RIGHT_BRACE_CHAR:
                       while (!LEFT_BRACE_STRING.equals(stack.peek())) {
                           result.add(stack.pop());
                      }
                       stack.pop();
                       break;
                   default:
                       while (!stack.isEmpty() && compare(stack.peek(), s)) {
                           result.add(stack.pop());
                      }
                       stack.push(s);
                       break;
              }
          }
      }

       while (!stack.isEmpty()) {
           result.add(stack.pop());
      }

       return result;
  }

   /**
    * Calculate the suffix expression
    */
   private static Integer calculate(List<String> result) {
       Stack<Integer> stack = new Stack<>();
       for (String s : result) {
           if (Character.isDigit(s.charAt(0))) {
               stack.push(Integer.parseInt(s));
          } else {
               Integer backInt = stack.pop();
               Integer frontInt = 0;
               char op = s.charAt(0);

               if (!(op == P || op == N)) {
                   frontInt = stack.pop();
              }

               int res = 0;
               switch (s.charAt(0)) {
                   case P:
                   case ADD_CHAR:
                       res = frontInt + backInt;
                       break;
                   case N:
                   case SUBTRACT_CHAR:
                       res = frontInt - backInt;
                       break;
                   case MULTIPLY_CHAR:
                       res = frontInt * backInt;
                       break;
                   case DIVISION_CHAR:
                       res = frontInt / backInt;
                       break;
                   default:
                       break;
              }
               stack.push(res);
          }
      }
       return stack.pop();
  }

   /**
    * string to list
    */
   private static List<String> string2List(String expression) {
       List<String> result = new ArrayList<>();
       StringBuilder num = new StringBuilder();
       for (int i = 0; i < expression.length(); i++) {
           if (Character.isDigit(expression.charAt(i))) {
               num.append(expression.charAt(i));
          } else {
               if (num.length() > 0) {
                   result.add(num.toString());
              }
               result.add(expression.charAt(i) + "");
               num = new StringBuilder();
          }
      }

       if (num.length() > 0) {
           result.add(num.toString());
      }

       return result;
  }

   /**
    * compare loginUser level
    */
   private static boolean compare(String peek, String cur) {
       boolean b = DIVISION_STRING.equals(cur) || MULTIPLY_STRING.equals(cur) || ADD_STRING.equals(cur) || SUBTRACT_STRING.equals(cur);
       if (MULTIPLY_STRING.equals(peek) && b) {
           return true;
      } else if (DIVISION_STRING.equals(peek) && b) {
           return true;
      } else if (ADD_STRING.equals(peek) && (ADD_STRING.equals(cur) || SUBTRACT_STRING.equals(cur))) {
           return true;
      } else {
           return SUBTRACT_STRING.equals(peek) && (ADD_STRING.equals(cur) || SUBTRACT_STRING.equals(cur));
      }
  }

   /**
    * Placeholder replacement resolver
    */
   private static class TimePlaceholderResolver implements PropertyPlaceholderHelper.PlaceholderResolver {

       private final String value;

       private final Date date;

       public TimePlaceholderResolver(String value, Date date) {
           this.value = value;
           this.date = date;
      }

       @Override
       public String resolvePlaceholder(String placeholderName) {
           try {
               return calculateTime(placeholderName, date);
          } catch (Exception ex) {
               log.error("resolve placeholder '{}' in [ {} ]", placeholderName, value, ex);
               return null;
          }
      }
  }

   /**
    * return the formatted date according to the corresponding date format
    */
   public static String getPlaceHolderTime(String expression, Date date) {
       if (StringUtils.isBlank(expression)) {
           return null;
      }
       if (null == date) {
           return null;
      }
       return calculateTime(expression, date);
  }

   /**
    * calculate time
    *
    * @param date date
    * @return calculate time
    */
   private static String calculateTime(String expression, Date date) {
       String value;
       try {
           Map.Entry<Date, String> entry = calcTimeExpression(expression, date);
           value = CustomDateUtil.format(entry.getKey(), entry.getValue());
      } catch (Exception e) {
           log.error(e.getMessage(), e);
           throw e;
      }
       return value;
  }

   /**
    * calculate time expression
    * @param expression expression
    * @param date       date
    * @return map with date, date format
    */
   public static Map.Entry<Date, String> calcTimeExpression(String expression, Date date) {
       Map.Entry<Date, String> resultEntry;
       if (expression.startsWith(Constants.ADD_YEARS)) {
           resultEntry = calcYears(expression, date);
      } else if (expression.startsWith(Constants.ADD_MONTHS)) {
           resultEntry = calcMonths(expression, date);
      } else if (expression.startsWith(Constants.MONTH_BEGIN)) {
           resultEntry = calcMonthBegin(expression, date);
      } else if (expression.startsWith(Constants.MONTH_END)) {
           resultEntry = calcMonthEnd(expression, date);
      } else if (expression.startsWith(Constants.YEAR_END)) {
           resultEntry = calcYearEnd(expression, date);
      } else if (expression.startsWith(Constants.WEEK_BEGIN)) {
           resultEntry = calcWeekStart(expression, date);
      } else if (expression.startsWith(Constants.WEEK_END)) {
           resultEntry = calcWeekEnd(expression, date);
      } else if (expression.startsWith(Constants.QUARTER_BEGIN)) {
           resultEntry = calcQuarterBegin(expression, date);
      } else if (expression.startsWith(Constants.QUARTER_END)) {
           resultEntry = calcQuarterEnd(expression, date);
      } else {
           resultEntry = calcMinutes(expression, date);
      }

       return resultEntry;
  }

   /**
    * get first day of a quarter
    * @param expression expression
    * @param date date
    */
   private static Map.Entry<Date, String> calcQuarterBegin(String expression, Date date) {
       String addQuarterExpr = expression.substring(QUARTER_BEGIN.length() + 1, expression.length() - 1);
       String[] params = addQuarterExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];
           Integer day = calculate(dayExpr);
           Date targetDate = CustomDateUtil.getQuarterBegin(date);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);
           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * get last day of a quarter
    * @param expression expression
    * @param date date
    */
   private static Map.Entry<Date, String> calcQuarterEnd(String expression, Date date) {
       String addQuarterExpr = expression.substring(QUARTER_END.length() + 1, expression.length() - 1);
       String[] params = addQuarterExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];
           Integer day = calculate(dayExpr);
           Date targetDate = CustomDateUtil.getQuarterEnd(date);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);
           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * get first day of month
    *
    * @param expression expression
    * @param date date
    * @return first day of month
    */
   public static Map.Entry<Date, String> calcMonthBegin(String expression, Date date) {
       String addMonthExpr = expression.substring(Constants.MONTH_BEGIN.length() + 1, expression.length() - 1);
       String[] params = addMonthExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];
           Integer day = calculate(dayExpr);
           Date targetDate = CustomDateUtil.getFirstDayOfMonth(date);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);

           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * get last day of month
    *
    * @param expression expression
    * @param date date
    * @return last day of month
    */
   public static Map.Entry<Date, String> calcMonthEnd(String expression, Date date) {
       String addMonthExpr = expression.substring(Constants.MONTH_END.length() + 1, expression.length() - 1);
       String[] params = addMonthExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];

           // 处理上个月
           if (dateFormat.endsWith("l1m")) {
               dateFormat = dateFormat.replace("l1m", "dd");
               String lastMonthOfDay = replacePlaceholders(String.format("$[add_months(%s, -1)]", dateFormat), date, true);
               date = CustomDateUtil.StringToDate(lastMonthOfDay, dateFormat);
          }
           Date targetDate = CustomDateUtil.getLastDayOfMonth(date);
           Integer day = calculate(dayExpr);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);

           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * get first day of a year
    * @param expression expression
    * @param date date
    */
   public static Map.Entry<Date, String> calcYearEnd(String expression, Date date) {
       String addYearExpr = expression.substring(Constants.YEAR_END.length() + 1, expression.length() - 1);
       String[] params = addYearExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];
           Date targetDate = CustomDateUtil.getLastDayOfYear(date);
           Integer day = calculate(dayExpr);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);

           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * get first day of week
    *
    * @param expression expression
    * @param date date
    * @return monday
    */
   public static Map.Entry<Date, String> calcWeekStart(String expression, Date date) {
       String addMonthExpr = expression.substring(Constants.WEEK_BEGIN.length() + 1, expression.length() - 1);
       String[] params = addMonthExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];
           Integer day = calculate(dayExpr);
           Date targetDate = CustomDateUtil.getMonday(date);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);
           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * get last day of week
    *
    * @param expression expression
    * @param date date
    * @return last day of week
    */
   public static Map.Entry<Date, String> calcWeekEnd(String expression, Date date) {
       String addMonthExpr = expression.substring(Constants.WEEK_END.length() + 1, expression.length() - 1);
       String[] params = addMonthExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String dayExpr = params[1];
           Integer day = calculate(dayExpr);
           Date targetDate = CustomDateUtil.getSunday(date);
           targetDate = org.apache.commons.lang.time.DateUtils.addDays(targetDate, day);

           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("Expression not valid");
  }

   /**
    * calc years expression
    *
    * @param expression expression
    * @param date date
    * @return calc months
    */
   public static Map.Entry<Date, String> calcYears(String expression, Date date) {
       String addYearExpr = expression.substring(ADD_YEARS.length() + 1, expression.length() - 1);
       String[] params = addYearExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String yearExpr = params[1];
           Integer addYear = calculate(yearExpr);
           Date targetDate = org.apache.commons.lang.time.DateUtils.addYears(date, addYear);

           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * calc months expression
    *
    * @param expression expression
    * @param date date
    * @return calc months
    */
   public static Map.Entry<Date, String> calcMonths(String expression, Date date) {
       String addMonthExpr = expression.substring(Constants.ADD_MONTHS.length() + 1, expression.length() - 1);
       String[] params = addMonthExpr.split(Constants.COMMA);

       if (params.length == 2) {
           String dateFormat = params[0];
           String monthExpr = params[1];
           Integer addMonth = calculate(monthExpr);
           Date targetDate = org.apache.commons.lang.time.DateUtils.addMonths(date, addMonth);

           return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
      }

       throw new RuntimeException("expression not valid");
  }

   /**
    * calculate time expression
    *
    * @param expression expression
    * @param date date
    * @return calculate time expression with date,format
    */
   public static Map.Entry<Date, String> calcMinutes(String expression, Date date) {
       if (expression.contains("+")) {
           int index = expression.lastIndexOf('+');
           if (Character.isDigit(expression.charAt(index + 1))) {
               String addMinuteExpr = expression.substring(index + 1);
               Date targetDate = org.apache.commons.lang.time.DateUtils
                  .addMinutes(date, calcMinutes(addMinuteExpr));
               String dateFormat = expression.substring(0, index);

               return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
          }
      } else if (expression.contains("-")) {
           int index = expression.lastIndexOf('-');
           if (Character.isDigit(expression.charAt(index + 1))) {
               String addMinuteExpr = expression.substring(index + 1);
               Date targetDate = DateUtils.addMinutes(date, -calcMinutes(addMinuteExpr));
               String dateFormat = expression.substring(0, index);

               return new AbstractMap.SimpleImmutableEntry<>(targetDate, dateFormat);
          }

           // yyyy-MM-dd/HH:mm:ss
           return new AbstractMap.SimpleImmutableEntry<>(date, expression);
      }

       // $[HH mm ss]
       return new AbstractMap.SimpleImmutableEntry<>(date, expression);
  }

   /**
    * calculate need minutes
    *
    * @param minuteExpression minute expression
    * @return calculate need minutes
    */
   public static Integer calcMinutes(String minuteExpression) {
       int index = minuteExpression.indexOf('/');

       String calcExpression;

       if (index == -1) {
           calcExpression = String.format("60*24*(%s)", minuteExpression);
      } else {

           calcExpression = String.format("60*24*(%s)%s", minuteExpression.substring(0, index),
               minuteExpression.substring(index));
      }
       return calculate(calcExpression);
  }
}

四、测试

package com.eyesmoons.date;

import java.util.Date;

public class TestExpression {
   public static void main(String[] args) {
       String result01 = TimePlaceholderUtils.replacePlaceholders("$[yyyyMMdd]", new Date(), true);
       System.out.println("当天:" + result01);
       String result02 = TimePlaceholderUtils.replacePlaceholders("$[yyyyMMdd-1]", new Date(), true);
       System.out.println("昨天:" + result02);
       String result03 = TimePlaceholderUtils.replacePlaceholders("$[yyyyMM01]", new Date(), true);
       System.out.println("本月第一天:" + result03);
       String result04 = TimePlaceholderUtils.replacePlaceholders("$[month_end(yyyyMMdd, 0)]", new Date(), true);
       System.out.println("本月最后一天:" + result04);
       String result05 = TimePlaceholderUtils.replacePlaceholders("$[add_months(yyyyMM01, -1)]", new Date(), true);
       System.out.println("上月第一天:" + result05);
       String result06 = TimePlaceholderUtils.replacePlaceholders("$[month_end(yyyyMMl1m, 0)]", new Date(), true);
       System.out.println("上月最后一天:" + result06);
       String result07 = TimePlaceholderUtils.replacePlaceholders("$[yyyy]", new Date(), true);
       System.out.println("每年:" + result07);
       String result08 = TimePlaceholderUtils.replacePlaceholders("$[add_years(yyyy, -1)]", new Date(), true);
       System.out.println("上年:" + result08);
       String result09 = TimePlaceholderUtils.replacePlaceholders("$[yyyyMM]", new Date(), true);
       System.out.println("每月:" + result09);
       String result10 = TimePlaceholderUtils.replacePlaceholders("$[add_months(yyyyMM, -1)]", new Date(), true);
       System.out.println("上月:" + result10);
       String result11 = TimePlaceholderUtils.replacePlaceholders("$[yyyy0101]", new Date(), true);
       System.out.println("每年第一天:" + result11);
       String result12 = TimePlaceholderUtils.replacePlaceholders("$[year_end(yyyyMMdd, 0)]", new Date(), true);
       System.out.println("每年最后一天:" + result12);
       String result13 = TimePlaceholderUtils.replacePlaceholders("$[quarter_begin(yyyyMMdd, 0)]", new Date(), true);
       System.out.println("每季度第一天:" + result13);
       String result14 = TimePlaceholderUtils.replacePlaceholders("$[quarter_end(yyyyMMdd, 0)]", new Date(), true);
       System.out.println("每季度最后一天:" + result14);
       String result15 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, -1)]", new Date(), true);
       System.out.println("周日:" + result15);
       String result16 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, 0)]", new Date(), true);
       System.out.println("周一:" + result16);
       String result17 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, 1)]", new Date(), true);
       System.out.println("周二:" + result17);
       String result18 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, 2)]", new Date(), true);
       System.out.println("周三:" + result18);
       String result19 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, 3)]", new Date(), true);
       System.out.println("周四:" + result19);
       String result20 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, 4)]", new Date(), true);
       System.out.println("周五:" + result20);
       String result21 = TimePlaceholderUtils.replacePlaceholders("$[week_begin(yyyyMMdd, 5)]", new Date(), true);
       System.out.println("周六:" + result21);
  }
}

结果如下:

当天:20230329
昨天:20230328
本月第一天:20230301
本月最后一天:20230331
上月第一天:20230201
上月最后一天:20230228
每年:2023
上年:2022
每月:202303
上月:202302
每年第一天:20230101
每年最后一天:20231231
每季度第一天:20230101
每季度最后一天:20230331
周日:20230326
周一:20230327
周二:20230328
周三:20230329
周四:20230330
周五:20230331
周六:20230401

五、注意

  1. 需要自行导入以下依赖

<!-- lombok -->
<dependency>
   <groupId>org.projectlombok</groupId>
   <artifactId>lombok</artifactId>
   <version>1.18.26</version>
</dependency>

<!-- logback -->
<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-classic</artifactId>
   <version>1.4.6</version>
</dependency>

<dependency>
   <groupId>ch.qos.logback</groupId>
   <artifactId>logback-core</artifactId>
   <version>1.4.6</version>
</dependency>
  1. PropertyPlaceholderHelper

    如果是springBoot项目,自带PropertyPlaceholderHelper依赖。


原文作者:毛毛小妖的笔记;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2019-04-04

  • 博文量
    70
  • 访问量
    46581