2025-02-11 15:27:15 +08:00
|
|
|
|
package com.ff.base.utils;
|
|
|
|
|
|
|
|
|
|
|
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
|
|
|
|
|
|
|
|
|
|
|
import java.lang.management.ManagementFactory;
|
|
|
|
|
|
import java.text.ParseException;
|
|
|
|
|
|
import java.text.SimpleDateFormat;
|
|
|
|
|
|
import java.time.*;
|
|
|
|
|
|
import java.time.format.DateTimeFormatter;
|
|
|
|
|
|
import java.time.temporal.TemporalAdjusters;
|
|
|
|
|
|
import java.util.*;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 时间工具类
|
|
|
|
|
|
*
|
|
|
|
|
|
* @author ff
|
|
|
|
|
|
*/
|
|
|
|
|
|
public class DateUtils extends org.apache.commons.lang3.time.DateUtils {
|
|
|
|
|
|
public static String YYYY = "yyyy";
|
|
|
|
|
|
|
|
|
|
|
|
public static String YYYY_MM = "yyyy-MM";
|
|
|
|
|
|
|
|
|
|
|
|
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";
|
|
|
|
|
|
|
|
|
|
|
|
public 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"};
|
|
|
|
|
|
|
|
|
|
|
|
public static String HHMMSS = "HH:mm:ss";
|
|
|
|
|
|
|
|
|
|
|
|
public static String DAY_START_TIME = "00:00:00";
|
|
|
|
|
|
|
|
|
|
|
|
public static String DAY_END_TIME = "23:59:59";
|
|
|
|
|
|
|
2025-04-01 16:13:44 +08:00
|
|
|
|
public static final String ISO_8601_FORMAT= "yyyy-MM-dd'T'HH:mm:ss";
|
|
|
|
|
|
|
2025-04-07 14:44:55 +08:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
public static final String ISO_8601_FORMAT_Z= "yyyy-MM-dd'T'HH:mm:ss'Z'";
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-11 15:27:15 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前Date型日期
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return Date() 当前日期
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getNowDate() {
|
|
|
|
|
|
return Instant.now().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前日期
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return {@link Long }
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Date getCurrentDate() {
|
|
|
|
|
|
return new Date();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前日期, 默认格式为yyyy-MM-dd
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return String
|
|
|
|
|
|
*/
|
|
|
|
|
|
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 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 int differentDaysByMillisecond(Date date1, Date date2) {
|
|
|
|
|
|
return Math.abs((int) ((date2.getTime() - date1.getTime()) / (1000 * 3600 * 24)));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 计算时间差
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param endDate 最后时间
|
|
|
|
|
|
* @param startTime 开始时间
|
|
|
|
|
|
* @return 时间差(天/小时/分钟)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String timeDistance(Date endDate, Date startTime) {
|
|
|
|
|
|
long nd = 1000 * 24 * 60 * 60;
|
|
|
|
|
|
long nh = 1000 * 60 * 60;
|
|
|
|
|
|
long nm = 1000 * 60;
|
|
|
|
|
|
// long ns = 1000;
|
|
|
|
|
|
// 获得两个时间的毫秒时间差异
|
|
|
|
|
|
long diff = endDate.getTime() - startTime.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 + "分钟";
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 增加 LocalDateTime ==> Date
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Date toDate(LocalDateTime temporalAccessor) {
|
|
|
|
|
|
ZonedDateTime zdt = temporalAccessor.atZone(ZoneId.systemDefault());
|
|
|
|
|
|
return Date.from(zdt.toInstant());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取格式化日期yymmd
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return {@link String }
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String getFormattedDate() {
|
|
|
|
|
|
ZonedDateTime nowUtcMinus4 = ZonedDateTime.now(ZoneId.of("UTC-4"));
|
|
|
|
|
|
|
|
|
|
|
|
String year = String.format("%02d", nowUtcMinus4.getYear() % 100);
|
|
|
|
|
|
String month = String.format("%02d", nowUtcMinus4.getMonthValue());
|
|
|
|
|
|
String day = String.valueOf(nowUtcMinus4.getDayOfMonth());
|
|
|
|
|
|
|
|
|
|
|
|
return year + month + day;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将日期格式化为gmt4
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param date 日期
|
|
|
|
|
|
* @return {@link String }
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String formatDateToGMT4(Date date) {
|
|
|
|
|
|
// 将 Date 转换为 ZonedDateTime
|
|
|
|
|
|
ZonedDateTime zdt = ZonedDateTime.ofInstant(date.toInstant(), ZoneId.of("GMT-4"));
|
|
|
|
|
|
// 定义日期时间格式
|
|
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss");
|
|
|
|
|
|
// 格式化并返回字符串
|
|
|
|
|
|
return zdt.format(formatter);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-04-01 16:13:44 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将时间戳转换为指定格式的时间字符串
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestamp 时间戳(毫秒)
|
|
|
|
|
|
* @param format 目标时间格式,例如:yyyy-MM-dd'T'HH:mm:ssXXX
|
|
|
|
|
|
* @param timeZone 时区,例如:GMT+8,UTC等
|
|
|
|
|
|
* @return 格式化后的时间字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String convertTimestampToFormattedDate(long timestamp, String format, String timeZone) {
|
|
|
|
|
|
// 创建日期格式化对象
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(format);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置时区为GMT+8
|
|
|
|
|
|
sdf.setTimeZone(TimeZone.getTimeZone(timeZone));
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为 Date 对象
|
|
|
|
|
|
Date date = new Date(timestamp);
|
|
|
|
|
|
|
|
|
|
|
|
// 返回格式化后的时间字符串
|
|
|
|
|
|
return sdf.format(date);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
2025-03-25 17:04:25 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 将毫秒时间戳转换为指定时区的时间,并按指定格式输出
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestampInMillis 毫秒级时间戳
|
|
|
|
|
|
* @param timeZone 时区(例如:America/New_York)
|
|
|
|
|
|
* @param format 时间格式(例如:yyyy-MM-dd HH:mm:ss)
|
|
|
|
|
|
* @return 格式化后的时间字符串
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static String convertTimeZone(long timestampInMillis, String timeZone, String format) {
|
|
|
|
|
|
// 将毫秒时间戳转换为 Instant
|
|
|
|
|
|
Instant instant = Instant.ofEpochMilli(timestampInMillis);
|
|
|
|
|
|
|
|
|
|
|
|
// 将 UTC 时间转换为指定时区的时间
|
|
|
|
|
|
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(timeZone));
|
|
|
|
|
|
|
|
|
|
|
|
// 格式化输出为指定格式的时间字符串
|
|
|
|
|
|
return zonedDateTime.format(DateTimeFormatter.ofPattern(format));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
2025-02-11 15:27:15 +08:00
|
|
|
|
/**
|
|
|
|
|
|
* 增加 LocalDate ==> Date
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Date toDate(LocalDate temporalAccessor) {
|
|
|
|
|
|
LocalDateTime localDateTime = LocalDateTime.of(temporalAccessor, LocalTime.of(0, 0, 0));
|
|
|
|
|
|
ZonedDateTime zdt = localDateTime.atZone(ZoneId.systemDefault());
|
|
|
|
|
|
return Date.from(zdt.toInstant());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 给定毫秒级时间戳,增加或扣除指定分钟
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestampMillis 初始时间戳(毫秒级)
|
|
|
|
|
|
* @param minutes 要增加或扣除的分钟数(正值为增加,负值为扣除)
|
|
|
|
|
|
* @return long 结果时间戳(毫秒级)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long addOrSubtractMinutes(long timestampMillis, int minutes) {
|
|
|
|
|
|
// 将分钟转换为毫秒,并加到时间戳上
|
|
|
|
|
|
return timestampMillis + minutes * 60 * 1000L;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 加或减一天
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestampDay 时间戳日期
|
|
|
|
|
|
* @param day 白天
|
|
|
|
|
|
* @return long
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long addOrSubtractDay(long timestampDay, int day) {
|
|
|
|
|
|
// 将分钟转换为毫秒,并加到时间戳上
|
|
|
|
|
|
return timestampDay + day * 60 * 1000L * 60 * 24;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取给定日期
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 不带时区的给定日期的起始时间戳(毫秒)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getDayStart(Calendar calendar) {
|
|
|
|
|
|
// 设置时间为当天的 00:00:00
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定时间戳指定时区的一天的开始时间
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestamp 时间戳
|
|
|
|
|
|
* @param timeZoneId 时区
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getDayStart(long timestamp, String timeZoneId) {
|
|
|
|
|
|
ZoneId zoneId = ZoneId.of(timeZoneId);
|
|
|
|
|
|
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(java.time.Instant.ofEpochMilli(timestamp), zoneId);
|
|
|
|
|
|
LocalDate localDate = zonedDateTime.toLocalDate();
|
|
|
|
|
|
LocalDateTime startOfDay = localDate.atStartOfDay();
|
|
|
|
|
|
ZonedDateTime startOfDayZoned = startOfDay.atZone(zoneId);
|
|
|
|
|
|
return startOfDayZoned.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取给定日期
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 不带时区的给定日期的结束时间戳(毫秒)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getDayEnd(Calendar calendar) {
|
|
|
|
|
|
// 设置时间为当天的 23:59:59
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 59);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 59);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 999);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定时间戳指定时区的一天的结束时间
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestamp 时间戳
|
|
|
|
|
|
* @param timeZoneId 时区
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getDayEnd(long timestamp, String timeZoneId) {
|
|
|
|
|
|
ZoneId zoneId = ZoneId.of(timeZoneId);
|
|
|
|
|
|
ZonedDateTime zonedDateTime = ZonedDateTime.ofInstant(java.time.Instant.ofEpochMilli(timestamp), zoneId);
|
|
|
|
|
|
LocalDate localDate = zonedDateTime.toLocalDate();
|
|
|
|
|
|
LocalDateTime endOfDay = localDate.atTime(23, 59, 59, 999999999);
|
|
|
|
|
|
ZonedDateTime endOfDayZoned = endOfDay.atZone(zoneId);
|
|
|
|
|
|
return endOfDayZoned.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取昨天的开始时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getYesterdayStart() {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
|
|
|
|
|
// 回溯一天
|
|
|
|
|
|
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
|
|
|
|
|
// 设置时间为当天的 00:00:00
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取昨天的结束时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getYesterdayEnd() {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
|
|
|
|
|
// 回溯一天
|
|
|
|
|
|
calendar.add(Calendar.DAY_OF_MONTH, -1);
|
|
|
|
|
|
// 设置时间为当天的 23:59:59
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 59);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 59);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 999);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取上周的开始时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getLastWeekBegin() {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
|
|
|
|
|
// 计算上周的起始日期(周一)
|
|
|
|
|
|
calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
|
|
|
|
|
|
calendar.add(Calendar.WEEK_OF_YEAR, -1);
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取上周的结束时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getLastWeekEnd() {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
|
|
|
|
|
// 计算上周的结束日期(周日)
|
|
|
|
|
|
calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY);
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 59);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 59);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 999);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取一周的开始时间
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getWeekBegin(Calendar calendar) {
|
|
|
|
|
|
// 设置一周的第一天为星期一
|
|
|
|
|
|
calendar.setFirstDayOfWeek(Calendar.MONDAY);
|
|
|
|
|
|
// 获取当前日期在本周的位置
|
|
|
|
|
|
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
|
|
|
|
|
|
// 计算需要回溯的天数
|
|
|
|
|
|
int daysToSubtract = (dayOfWeek == Calendar.SUNDAY ? 6 : dayOfWeek - 2);
|
|
|
|
|
|
calendar.add(Calendar.DAY_OF_MONTH, -daysToSubtract);
|
|
|
|
|
|
// 设置时间为当天的 00:00:00
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取一周的结束时间
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getWeekEnd(Calendar calendar) {
|
|
|
|
|
|
// 设置一周的第一天为星期一
|
|
|
|
|
|
calendar.setFirstDayOfWeek(Calendar.MONDAY);
|
|
|
|
|
|
// 获取当前日期在本周的位置
|
|
|
|
|
|
int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
|
|
|
|
|
|
// 计算需要前进的天数
|
|
|
|
|
|
int daysToAdd = (dayOfWeek == Calendar.SUNDAY ? 0 : 7 - (dayOfWeek - 1));
|
|
|
|
|
|
calendar.add(Calendar.DAY_OF_MONTH, daysToAdd);
|
|
|
|
|
|
// 设置时间为当天的 23:59:59
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 59);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 59);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 999);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前月份的开始时间
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getMonthStart(Calendar calendar) {
|
|
|
|
|
|
// 设置时间为当月的第一天
|
|
|
|
|
|
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
|
|
|
|
|
// 设置时间为当天的 00:00:00
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取当前月份的结束时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getMonthEnd(Calendar calendar) {
|
|
|
|
|
|
// 设置时间为当月的最后一天
|
|
|
|
|
|
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH));
|
|
|
|
|
|
// 设置时间为当天的 23:59:59
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 23);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 59);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 59);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 999);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取上个月的开始时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getLastMonthStart() {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
|
|
|
|
|
// 计算上个月的起始日期(1号)
|
|
|
|
|
|
calendar.add(Calendar.MONTH, -1);
|
|
|
|
|
|
calendar.set(Calendar.DAY_OF_MONTH, 1);
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 0);
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 0);
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 0);
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 0);
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取上个月的结束时间(不带时区)
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return 时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Long getLastMonthEnd() {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"));
|
|
|
|
|
|
calendar.add(Calendar.MONTH, -1); // 回退一个月
|
|
|
|
|
|
|
|
|
|
|
|
// 计算上个月的结束日期(最后一天)
|
|
|
|
|
|
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); // 设置日期为当月最后一天
|
|
|
|
|
|
calendar.set(Calendar.HOUR_OF_DAY, 23); // 设置小时为23
|
|
|
|
|
|
calendar.set(Calendar.MINUTE, 59); // 设置分钟为59
|
|
|
|
|
|
calendar.set(Calendar.SECOND, 59); // 设置秒为59
|
|
|
|
|
|
calendar.set(Calendar.MILLISECOND, 999); // 设置毫秒为999
|
|
|
|
|
|
return calendar.getTimeInMillis();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断时间戳 A 距离时间戳 B 近还是距离时间戳 C 近
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestampA 时间戳 A
|
|
|
|
|
|
* @param timestampB 时间戳 B
|
|
|
|
|
|
* @param timestampC 时间戳 C
|
|
|
|
|
|
* @return 返回 true 表示时间戳 A 更接近时间戳 B,返回 false 表示时间戳 A 更接近时间戳 C
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boolean isCloserToB(long timestampA, long timestampB, long timestampC) {
|
|
|
|
|
|
long diffAB = Math.abs(timestampA - timestampB);
|
|
|
|
|
|
long diffAC = Math.abs(timestampA - timestampC);
|
|
|
|
|
|
return diffAB < diffAC;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定时间戳次日指定时区指定时间的时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param utcTimestamp utc时间戳
|
|
|
|
|
|
* @param date 具体时间
|
|
|
|
|
|
* @param timeZonId 指定时区
|
|
|
|
|
|
* @return 只改变时区 不改变具体日期的时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long getTomorrowTimeByZonId(long utcTimestamp, Date date, String timeZonId) {
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(HHMMSS);
|
|
|
|
|
|
String format = sdf.format(date);
|
|
|
|
|
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
|
|
|
|
|
|
LocalTime localTime = LocalTime.parse(format, timeFormatter);
|
|
|
|
|
|
// 将时间戳转换为 Instant
|
|
|
|
|
|
Instant instant = Instant.ofEpochMilli(addOrSubtractDay(utcTimestamp, 1));
|
|
|
|
|
|
ZoneId zoneId = ZoneId.of(timeZonId);
|
|
|
|
|
|
LocalDate localDate = instant.atZone(zoneId).toLocalDate();
|
|
|
|
|
|
LocalDateTime tomorrowDrawStartTime = localDate.atTime(localTime);
|
|
|
|
|
|
return tomorrowDrawStartTime.atZone(zoneId).toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 指定时区并具体时间的的实时时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param date 具体时间
|
|
|
|
|
|
* @param timeZonId 时区
|
|
|
|
|
|
* @return 只改变时区 不改变具体日期的时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long getTodayTimeByZonId(Date date, String timeZonId) {
|
|
|
|
|
|
// 获取今日指定时间后的时间戳
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(HHMMSS);
|
|
|
|
|
|
String format = sdf.format(date);
|
|
|
|
|
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
|
|
|
|
|
|
LocalTime localTime = LocalTime.parse(format, timeFormatter);
|
|
|
|
|
|
LocalDate currentDate = LocalDate.now();
|
|
|
|
|
|
LocalDateTime todayDrawStartTime = currentDate.atTime(localTime);
|
|
|
|
|
|
ZoneId zoneId = ZoneId.of(timeZonId);
|
|
|
|
|
|
return todayDrawStartTime.atZone(zoneId).toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取下周指定周几的几点的指定时区时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param dayOfWeek 周几,1-7表示周一到周日
|
|
|
|
|
|
* @param date 具体时间,Date对象
|
|
|
|
|
|
* @return UTC时间戳(毫秒)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long getNextWeekTimestamp(int dayOfWeek, Date date, ZoneId zoneId) {
|
|
|
|
|
|
// 将Date对象转换为LocalDateTime对象
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(HHMMSS);
|
|
|
|
|
|
String format = sdf.format(date);
|
|
|
|
|
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
|
|
|
|
|
|
LocalTime localTime = LocalTime.parse(format, timeFormatter);
|
|
|
|
|
|
// 获取当前日期时间
|
|
|
|
|
|
ZonedDateTime now = ZonedDateTime.now(zoneId);
|
|
|
|
|
|
// 找到本周的周几
|
|
|
|
|
|
ZonedDateTime startOfWeek = now.with(dayOfWeek < now.getDayOfWeek().getValue() ? TemporalAdjusters.previousOrSame(DayOfWeek.of(dayOfWeek)) : TemporalAdjusters.nextOrSame(DayOfWeek.of(dayOfWeek)));
|
|
|
|
|
|
|
|
|
|
|
|
// 加上一个完整的星期,得到下周的周几
|
|
|
|
|
|
ZonedDateTime nextWeekStart = startOfWeek.plusWeeks(1);
|
|
|
|
|
|
|
|
|
|
|
|
// 设置指定的时间
|
|
|
|
|
|
ZonedDateTime targetDateTime = nextWeekStart.withHour(localTime.getHour()).withMinute(localTime.getMinute()).withSecond(localTime.getSecond()).withNano(0);
|
|
|
|
|
|
|
|
|
|
|
|
// 转换为时间戳(毫秒)
|
|
|
|
|
|
return targetDateTime.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定时区当前周指定周几的几点的时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param dayOfWeek 周几,1-7表示周一到周日
|
|
|
|
|
|
* @param date 具体时间,Date对象
|
|
|
|
|
|
* @return 时间戳(毫秒)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long getCurrentWeekTimestamp(int dayOfWeek, Date date, ZoneId zoneId) {
|
|
|
|
|
|
// 将Date对象转换为LocalDateTime对象
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(HHMMSS);
|
|
|
|
|
|
String format = sdf.format(date);
|
|
|
|
|
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
|
|
|
|
|
|
LocalTime localTime = LocalTime.parse(format, timeFormatter);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前日期时间
|
|
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前周的指定周几的日期时间
|
|
|
|
|
|
LocalDateTime currentWeekDateTime = now.with(dayOfWeek < now.getDayOfWeek().getValue() ? TemporalAdjusters.previousOrSame(DayOfWeek.of(dayOfWeek)) : TemporalAdjusters.nextOrSame(DayOfWeek.of(dayOfWeek)))
|
|
|
|
|
|
.withHour(localTime.getHour())
|
|
|
|
|
|
.withMinute(localTime.getMinute())
|
|
|
|
|
|
.withSecond(localTime.getSecond())
|
|
|
|
|
|
.withNano(0);
|
|
|
|
|
|
|
|
|
|
|
|
// 将LocalDateTime转换为ZonedDateTime,使用UTC时区
|
|
|
|
|
|
ZonedDateTime zonedDateTime = currentWeekDateTime.atZone(zoneId);
|
|
|
|
|
|
|
|
|
|
|
|
// 将ZonedDateTime转换为时间戳(毫秒)
|
|
|
|
|
|
return zonedDateTime.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取下月指定日的几点的时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param dayOfMonth 指定日,1-31表示
|
|
|
|
|
|
* @param date 具体时间,Date对象
|
|
|
|
|
|
* @param month 下几月
|
|
|
|
|
|
* @return 时间戳(毫秒)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long getNextMonthTimestamp(int dayOfMonth, Date date, ZoneId zoneId, int month) {
|
|
|
|
|
|
// 将Date对象转换为LocalDateTime对象
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(HHMMSS);
|
|
|
|
|
|
String format = sdf.format(date);
|
|
|
|
|
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
|
|
|
|
|
|
LocalTime localTime = LocalTime.parse(format, timeFormatter);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前日期时间
|
|
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
|
|
|
|
|
|
|
// 获取下个月的年份和月份
|
|
|
|
|
|
YearMonth nextMonth = YearMonth.from(now).plusMonths(month);
|
|
|
|
|
|
int maxDayNum = nextMonth.lengthOfMonth();
|
|
|
|
|
|
if (dayOfMonth > maxDayNum) {
|
|
|
|
|
|
dayOfMonth = maxDayNum;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建下个月指定日的LocalDateTime对象
|
|
|
|
|
|
LocalDateTime nextMonthDateTime = LocalDateTime.of(nextMonth.getYear(), nextMonth.getMonth(), dayOfMonth,
|
|
|
|
|
|
localTime.getHour(), localTime.getMinute(), localTime.getSecond(), 0);
|
|
|
|
|
|
|
|
|
|
|
|
// 将LocalDateTime转换为ZonedDateTime,使用UTC时区
|
|
|
|
|
|
ZonedDateTime zonedDateTime = nextMonthDateTime.atZone(zoneId);
|
|
|
|
|
|
|
|
|
|
|
|
// 将ZonedDateTime转换为时间戳(毫秒)
|
|
|
|
|
|
return zonedDateTime.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取本月指定日的几点的时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param dayOfMonth 指定日,1-31表示
|
|
|
|
|
|
* @param date 具体时间,Date对象
|
|
|
|
|
|
* @return 时间戳(毫秒)
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long getCurrentMonthTimestamp(int dayOfMonth, Date date, ZoneId zoneId) {
|
|
|
|
|
|
// 将Date对象转换为LocalDateTime对象
|
|
|
|
|
|
SimpleDateFormat sdf = new SimpleDateFormat(HHMMSS);
|
|
|
|
|
|
String format = sdf.format(date);
|
|
|
|
|
|
DateTimeFormatter timeFormatter = DateTimeFormatter.ofPattern(HHMMSS);
|
|
|
|
|
|
LocalTime localTime = LocalTime.parse(format, timeFormatter);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前日期时间
|
|
|
|
|
|
LocalDateTime now = LocalDateTime.now();
|
|
|
|
|
|
// 获取本月的年份和月份
|
|
|
|
|
|
YearMonth currentMonth = YearMonth.from(now);
|
|
|
|
|
|
int maxDayNum = currentMonth.lengthOfMonth();
|
|
|
|
|
|
if (dayOfMonth > maxDayNum) {
|
|
|
|
|
|
dayOfMonth = maxDayNum;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 创建本月指定日的LocalDateTime对象
|
|
|
|
|
|
LocalDateTime currentMonthDateTime = LocalDateTime.of(currentMonth.getYear(), currentMonth.getMonth(), dayOfMonth,
|
|
|
|
|
|
localTime.getHour(), localTime.getMinute(), localTime.getSecond(), 0);
|
|
|
|
|
|
|
|
|
|
|
|
// 将LocalDateTime转换为ZonedDateTime,使用UTC时区
|
|
|
|
|
|
ZonedDateTime zonedDateTime = currentMonthDateTime.atZone(zoneId);
|
|
|
|
|
|
|
|
|
|
|
|
// 将ZonedDateTime转换为时间戳(毫秒)
|
|
|
|
|
|
return zonedDateTime.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将时间戳转换为UTC0时区的时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timeZoneId 时区id
|
|
|
|
|
|
* @param timestamp 时间戳
|
|
|
|
|
|
* @return UTC0时区的时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long covertToUTCtimestamp(String timeZoneId, long timestamp) {
|
|
|
|
|
|
// 将时间戳转换为 Instant 对象
|
|
|
|
|
|
Instant instant = Instant.ofEpochMilli(timestamp);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用指定的时区将 Instant 对象转换为 ZonedDateTime 对象
|
|
|
|
|
|
ZonedDateTime zonedDateTime = instant.atZone(ZoneId.of(timeZoneId));
|
|
|
|
|
|
ZonedDateTime zonedDateTime1 = zonedDateTime.withZoneSameLocal(ZoneOffset.UTC);
|
|
|
|
|
|
// 将 ZonedDateTime 对象转换为 UTC0 时区的 Instant 对象
|
|
|
|
|
|
|
|
|
|
|
|
// 获取 UTC0 时区的时间戳(以毫秒为单位)
|
|
|
|
|
|
return zonedDateTime1.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将UTC时间戳转换为指定时区的时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timeZoneId 时区id
|
|
|
|
|
|
* @param timestamp 时间戳
|
|
|
|
|
|
* @return 指定时区的时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long covertUTCTotimeZonetimestamp(String timeZoneId, long timestamp) {
|
|
|
|
|
|
// 将时间戳转换为 Instant 对象
|
|
|
|
|
|
Instant instant = Instant.ofEpochMilli(timestamp);
|
|
|
|
|
|
|
|
|
|
|
|
// 使用指定的时区将 Instant 对象转换为 ZonedDateTime 对象
|
|
|
|
|
|
ZonedDateTime zonedDateTime = instant.atZone(ZoneOffset.UTC);
|
|
|
|
|
|
ZonedDateTime zonedDateTime1 = zonedDateTime.withZoneSameLocal(ZoneId.of(timeZoneId));
|
|
|
|
|
|
// 获取 指定 时区的时间戳(以毫秒为单位)
|
|
|
|
|
|
return zonedDateTime1.toInstant().toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否是指定时区的当天的0点
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestamp
|
|
|
|
|
|
* @param timeZone
|
|
|
|
|
|
* @return
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boolean isMidnight(long timestamp, TimeZone timeZone) {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(timeZone);
|
|
|
|
|
|
calendar.setTimeInMillis(timestamp);
|
|
|
|
|
|
|
|
|
|
|
|
return calendar.get(Calendar.HOUR_OF_DAY) == 0 &&
|
|
|
|
|
|
calendar.get(Calendar.MINUTE) == 0 &&
|
|
|
|
|
|
calendar.get(Calendar.SECOND) == 0 &&
|
|
|
|
|
|
calendar.get(Calendar.MILLISECOND) == 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否是指定时区的周一的0点
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestamp 时间戳
|
|
|
|
|
|
* @param timeZone 指定时区
|
|
|
|
|
|
* @return 是否是周一的0点
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boolean isMondayMidnight(long timestamp, TimeZone timeZone) {
|
|
|
|
|
|
Calendar calendar = Calendar.getInstance(timeZone);
|
|
|
|
|
|
calendar.setTimeInMillis(timestamp);
|
|
|
|
|
|
|
|
|
|
|
|
return isMidnight(timestamp, timeZone) && calendar.get(Calendar.DAY_OF_WEEK) == Calendar.MONDAY;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将 ISO 8601 格式的时间字符串转换为毫秒时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param isoDate ISO 8601 格式的时间字符串,例如 "2025-05-10T08:23:34Z"
|
|
|
|
|
|
* @return 从 Unix epoch 开始的毫秒时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static long convertToMilliseconds(String isoDate) {
|
|
|
|
|
|
Instant instant = Instant.parse(isoDate);
|
|
|
|
|
|
return instant.toEpochMilli();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将 ZoneId 转换为 TimeZone
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param zoneId 要转换的 ZoneId
|
|
|
|
|
|
* @return 对应的 TimeZone
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static TimeZone zoneIdToTimeZone(ZoneId zoneId) {
|
|
|
|
|
|
return TimeZone.getTimeZone(zoneId.getId());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取指定星期几的开始和结束UTC时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param dayOfWeek 星期几,1-7,1表示星期一,7表示星期日
|
|
|
|
|
|
* @return 包含开始和结束UTC时间戳的数组,第一个元素是开始时间戳,第二个元素是结束时间戳
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Map<String, Object> getStartAndEndUTCTimestampOfDayOfWeek(int dayOfWeek) {
|
|
|
|
|
|
if (dayOfWeek < 1 || dayOfWeek > 7) {
|
|
|
|
|
|
throw new IllegalArgumentException("dayOfWeek must be between 1 and 7");
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 获取当前日期
|
|
|
|
|
|
LocalDate today = LocalDate.now(ZoneOffset.UTC);
|
|
|
|
|
|
// 计算本周的开始日期(星期一)
|
|
|
|
|
|
LocalDate monday = today.with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
|
|
|
|
|
|
// 计算指定星期几的日期
|
|
|
|
|
|
LocalDate targetDay = monday.plusDays(dayOfWeek - 1);
|
|
|
|
|
|
|
|
|
|
|
|
// 计算指定星期几的开始时间(00:00:00 UTC)
|
|
|
|
|
|
ZonedDateTime startOfDay = targetDay.atStartOfDay(ZoneOffset.UTC);
|
|
|
|
|
|
// 计算指定星期几的结束时间(23:59:59 UTC)
|
|
|
|
|
|
ZonedDateTime endOfDay = targetDay.atTime(LocalTime.MAX).atZone(ZoneOffset.UTC);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取开始和结束时间戳
|
|
|
|
|
|
long startTimestamp = startOfDay.toInstant().toEpochMilli();
|
|
|
|
|
|
long endTimestamp = endOfDay.toInstant().toEpochMilli();
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
|
|
|
|
map.put("beginTime", startTimestamp);
|
|
|
|
|
|
map.put("endTime", endTimestamp);
|
|
|
|
|
|
return map;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取本月指定月几号的开始和结束UTC时间戳
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param dayOfMonth 本月几号,1-31
|
|
|
|
|
|
* @return 包含开始和结束UTC时间戳的Map,键分别为"beginTime"和"endTime"
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Map<String, Object> getStartAndEndUTCTimestampOfDayOfMonth(int dayOfMonth) {
|
|
|
|
|
|
// 获取当前日期
|
|
|
|
|
|
LocalDate today = LocalDate.now(ZoneOffset.UTC);
|
|
|
|
|
|
// 获取本月的年份和月份
|
|
|
|
|
|
YearMonth currentMonth = YearMonth.from(today);
|
|
|
|
|
|
int maxDayNum = currentMonth.lengthOfMonth();
|
|
|
|
|
|
if (dayOfMonth > maxDayNum) {
|
|
|
|
|
|
dayOfMonth = maxDayNum;
|
|
|
|
|
|
}
|
|
|
|
|
|
// 获取当前年份和月份
|
|
|
|
|
|
int year = today.getYear();
|
|
|
|
|
|
int month = today.getMonthValue();
|
|
|
|
|
|
|
|
|
|
|
|
// 构建指定月几号的日期
|
|
|
|
|
|
LocalDate targetDay;
|
|
|
|
|
|
try {
|
|
|
|
|
|
targetDay = LocalDate.of(year, month, dayOfMonth);
|
|
|
|
|
|
} catch (DateTimeException e) {
|
|
|
|
|
|
throw new IllegalArgumentException("Invalid dayOfMonth for the current month", e);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
// 计算指定月几号的开始时间(00:00:00 UTC)
|
|
|
|
|
|
ZonedDateTime startOfDay = targetDay.atStartOfDay(ZoneOffset.UTC);
|
|
|
|
|
|
// 计算指定月几号的结束时间(23:59:59 UTC)
|
|
|
|
|
|
ZonedDateTime endOfDay = targetDay.atTime(LocalTime.MAX).atZone(ZoneOffset.UTC);
|
|
|
|
|
|
|
|
|
|
|
|
// 获取开始和结束时间戳
|
|
|
|
|
|
long startTimestamp = startOfDay.toInstant().toEpochMilli();
|
|
|
|
|
|
long endTimestamp = endOfDay.toInstant().toEpochMilli();
|
|
|
|
|
|
|
|
|
|
|
|
Map<String, Object> map = new HashMap<>();
|
|
|
|
|
|
map.put("beginTime", startTimestamp);
|
|
|
|
|
|
map.put("endTime", endTimestamp);
|
|
|
|
|
|
return map;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断两个毫秒级时间戳是否为同一天
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param timestamp1 第一个时间戳
|
|
|
|
|
|
* @param timestamp2 第二个时间戳
|
|
|
|
|
|
* @return 如果两个时间戳属于同一天,返回true;否则返回false
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boolean isSameDay(long timestamp1, long timestamp2) {
|
|
|
|
|
|
// 将时间戳转换为 LocalDate
|
|
|
|
|
|
LocalDate date1 = Instant.ofEpochMilli(timestamp1)
|
|
|
|
|
|
.atZone(ZoneId.systemDefault()) // 使用系统默认时区
|
|
|
|
|
|
.toLocalDate();
|
|
|
|
|
|
|
|
|
|
|
|
LocalDate date2 = Instant.ofEpochMilli(timestamp2)
|
|
|
|
|
|
.atZone(ZoneId.systemDefault()) // 使用系统默认时区
|
|
|
|
|
|
.toLocalDate();
|
|
|
|
|
|
|
|
|
|
|
|
// 比较日期部分是否相同
|
|
|
|
|
|
return date1.isEqual(date2);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 获取 UTC 时区的当前日期,并返回 java.util.Date 类型
|
|
|
|
|
|
*
|
|
|
|
|
|
* @return java.util.Date 对象,表示 UTC 时区的当前日期
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Date getUTCDate() {
|
|
|
|
|
|
// 获取 UTC 时区的当前时间
|
|
|
|
|
|
ZonedDateTime utcTime = ZonedDateTime.now(ZoneId.of("UTC"));
|
|
|
|
|
|
|
|
|
|
|
|
// 提取 UTC 时区的日期部分
|
|
|
|
|
|
ZonedDateTime utcDateTime = utcTime.toLocalDate().atStartOfDay(ZoneId.of("UTC"));
|
|
|
|
|
|
|
|
|
|
|
|
// 将 ZonedDateTime 转换为 java.util.Date
|
|
|
|
|
|
return Date.from(utcDateTime.toInstant());
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 将 LocalTime 转换为 Date
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param localTime LocalTime对象
|
|
|
|
|
|
* @return Date对象
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static Date convertToDate(LocalTime localTime) {
|
|
|
|
|
|
// 使用当前日期作为参考日期
|
|
|
|
|
|
LocalDate today = LocalDate.now();
|
|
|
|
|
|
|
|
|
|
|
|
// 将 LocalTime 和 LocalDate 结合成 LocalDateTime
|
|
|
|
|
|
LocalDateTime localDateTime = LocalDateTime.of(today, localTime);
|
|
|
|
|
|
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
|
|
|
|
|
|
String format = localDateTime.format(formatter);
|
|
|
|
|
|
// 将 LocalDateTime 转换为 Date
|
|
|
|
|
|
return DateUtils.parseDate(format);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
|
* 判断是否在指定时间段内
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param value 要判断的时间戳
|
|
|
|
|
|
* @param minValue 开始时间戳
|
|
|
|
|
|
* @param maxValue 结束时间戳
|
|
|
|
|
|
* @return 是否在指定时间段内
|
|
|
|
|
|
*/
|
|
|
|
|
|
public static boolean isBetween(Long value, Long minValue, Long maxValue) {
|
|
|
|
|
|
return value >= minValue && value <= maxValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|