mirror of
https://github.com/tiennm99/zfoo.git
synced 2026-10-03 11:12:53 +00:00
docs: Translate the Chinese comments in the event module into English.
This commit is contained in:
1 parent
9dd775abf2
commit
d9fd135208
11 files changed
+103
-100
No files matched your search
@@ -63,13 +63,13 @@ public class SchedulerContext implements ApplicationListener<ApplicationContextE
|
||||
@Override
|
||||
public void onApplicationEvent(ApplicationContextEvent event) {
|
||||
if (event instanceof ContextRefreshedEvent) {
|
||||
// 初始化上下文
|
||||
// Initialize context
|
||||
SchedulerContext.instance = this;
|
||||
instance.applicationContext = event.getApplicationContext();
|
||||
inject();
|
||||
// 启动位于SchedulerBus的static静态代码块中
|
||||
// Startup is performed in the static initializer block of SchedulerBus
|
||||
} else if (event instanceof ContextClosedEvent) {
|
||||
// 反射获取executor,关闭掉
|
||||
// Obtain the executor via reflection and shut it down
|
||||
shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ import java.lang.reflect.Modifier;
|
||||
public abstract class EnhanceUtils {
|
||||
|
||||
static {
|
||||
// 适配Tomcat,因为Tomcat不是用的默认的类加载器,而Javassist用的是默认的加载器
|
||||
// Adapt for Tomcat: Tomcat does not use the default class loader, but Javassist relies on it
|
||||
var classArray = new Class<?>[]{
|
||||
IScheduler.class
|
||||
};
|
||||
@@ -49,29 +49,29 @@ public abstract class EnhanceUtils {
|
||||
Object bean = reflectScheduler.getBean();
|
||||
Method method = reflectScheduler.getMethod();
|
||||
|
||||
// 定义类名称
|
||||
// Define the class name
|
||||
CtClass enhanceClazz = classPool.makeClass(EnhanceUtils.class.getName() + StringUtils.capitalize(NamespaceHandler.SCHEDULER) + UuidUtils.getLocalIntId());
|
||||
enhanceClazz.addInterface(classPool.get(IScheduler.class.getName()));
|
||||
|
||||
// 定义类中的一个成员
|
||||
// Define a field in the class
|
||||
CtField field = new CtField(classPool.get(bean.getClass().getName()), "bean", enhanceClazz);
|
||||
field.setModifiers(Modifier.PRIVATE);
|
||||
enhanceClazz.addField(field);
|
||||
|
||||
// 定义类的构造器
|
||||
// Define the constructor
|
||||
CtConstructor constructor = new CtConstructor(classPool.get(new String[]{bean.getClass().getName()}), enhanceClazz);
|
||||
constructor.setBody("{this.bean=$1;}");
|
||||
constructor.setModifiers(Modifier.PUBLIC);
|
||||
enhanceClazz.addConstructor(constructor);
|
||||
|
||||
// 定义类实现的接口方法
|
||||
// Define the interface method implementation
|
||||
CtMethod invokeMethod = new CtMethod(classPool.get(void.class.getName()), "invoke", null, enhanceClazz);
|
||||
invokeMethod.setModifiers(Modifier.PUBLIC + Modifier.FINAL);
|
||||
String invokeMethodBody = "{this.bean." + method.getName() + "();}";
|
||||
invokeMethod.setBody(invokeMethodBody);
|
||||
enhanceClazz.addMethod(invokeMethod);
|
||||
|
||||
// 释放缓存
|
||||
// Release cached class
|
||||
enhanceClazz.detach();
|
||||
|
||||
Class<?> resultClazz = enhanceClazz.toClass(IScheduler.class);
|
||||
|
||||
@@ -17,7 +17,8 @@ import com.zfoo.protocol.util.ReflectionUtils;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* 动态代理被Scheduler注解标注的方法,为了避免反射最终会用javassist字节码增强的方法去代理ReflectScheduler
|
||||
* Dynamic proxy for methods annotated with @Scheduler.
|
||||
* To avoid reflection overhead, Javassist bytecode enhancement is used to proxy ReflectScheduler.
|
||||
*
|
||||
* @author godotg
|
||||
*/
|
||||
|
||||
@@ -23,8 +23,8 @@ import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* EN: Trigger timestamp, as long as the current timestamp is greater than this trigger event stamp, it is considered triggerable
|
||||
* CN: 触发时间戳,只要当前时间戳大于这个触发事件戳都视为可以触发
|
||||
* Trigger timestamp: the scheduler fires whenever the current timestamp exceeds this value.
|
||||
*
|
||||
* @author godotg
|
||||
*/
|
||||
public class SchedulerDefinition {
|
||||
|
||||
@@ -39,19 +39,19 @@ public abstract class SchedulerBus {
|
||||
|
||||
private static final List<SchedulerDefinition> schedulerDefList = new CopyOnWriteArrayList<>();
|
||||
/**
|
||||
* scheduler默认只有一个单线程的线程池
|
||||
* Scheduler uses a single-threaded executor by default
|
||||
*/
|
||||
private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(new SchedulerThreadFactory(1));
|
||||
|
||||
|
||||
/**
|
||||
* 上一次trigger触发时间
|
||||
* Timestamp of the last trigger invocation
|
||||
*/
|
||||
private static long lastTriggerTimestamp = 0L;
|
||||
|
||||
|
||||
/**
|
||||
* 在scheduler中,最小的triggerTimestamp
|
||||
* The minimum triggerTimestamp among all registered schedulers
|
||||
*/
|
||||
private static long minTriggerTimestamp = 0L;
|
||||
|
||||
@@ -101,7 +101,8 @@ public abstract class SchedulerBus {
|
||||
}
|
||||
|
||||
/**
|
||||
* 每一秒执行一次,如果这个任务执行时间过长超过,比如10秒,执行完成后,不会再执行10次
|
||||
* Executed once per second. If this task takes longer than expected (e.g. 10 seconds),
|
||||
* it will NOT catch up by running 10 times after completion.
|
||||
*/
|
||||
private static void triggerPerSecond() {
|
||||
var currentTimeMillis = TimeUtils.currentTimeMillis();
|
||||
@@ -111,7 +112,7 @@ public abstract class SchedulerBus {
|
||||
}
|
||||
|
||||
|
||||
// 有人向前调整过机器时间,重新计算scheduler里的triggerTimestamp
|
||||
// Someone moved the system clock backward; recalculate triggerTimestamp for all schedulers
|
||||
// var diff = timestamp - lastTriggerTimestamp;
|
||||
if (currentTimeMillis < lastTriggerTimestamp) {
|
||||
for (SchedulerDefinition schedulerDef : schedulerDefList) {
|
||||
@@ -121,10 +122,10 @@ public abstract class SchedulerBus {
|
||||
refreshMinTriggerTimestamp();
|
||||
}
|
||||
|
||||
// diff > 0, 没有人调整时间或者有人向后调整过机器时间,可以忽略,因为向后调整时间时间戳一定会大于triggerTimestamp,所以一定会触发
|
||||
// diff > 0: no clock adjustment, or clock was moved forward; can be ignored since the timestamp will exceed triggerTimestamp and will always trigger
|
||||
lastTriggerTimestamp = currentTimeMillis;
|
||||
|
||||
// 如果minSchedulerTriggerTimestamp大于timestamp,说明没有可执行的scheduler
|
||||
// If minTriggerTimestamp is greater than currentTimeMillis, no scheduler is ready to execute
|
||||
if (currentTimeMillis < minTriggerTimestamp) {
|
||||
return;
|
||||
}
|
||||
@@ -134,7 +135,7 @@ public abstract class SchedulerBus {
|
||||
for (var scheduler : schedulerDefList) {
|
||||
var triggerTimestamp = scheduler.getTriggerTimestamp();
|
||||
if (triggerTimestamp <= currentTimeMillis) {
|
||||
// 到达触发时间,则执行runnable方法
|
||||
// Trigger time reached, invoke the scheduler
|
||||
try {
|
||||
scheduler.getScheduler().invoke();
|
||||
} catch (Exception e) {
|
||||
@@ -142,7 +143,7 @@ public abstract class SchedulerBus {
|
||||
} catch (Throwable t) {
|
||||
logger.error("scheduler invoke error", t);
|
||||
}
|
||||
// 重新设置下一次的触发时间戳
|
||||
// Reset the next trigger timestamp
|
||||
triggerTimestamp = TimeUtils.nextTimestampByCronExpression(scheduler.getCronExpression(), timestampZonedDataTime);
|
||||
scheduler.setTriggerTimestamp(triggerTimestamp);
|
||||
}
|
||||
@@ -160,7 +161,7 @@ public abstract class SchedulerBus {
|
||||
|
||||
|
||||
/**
|
||||
* 不断执行的周期循环任务
|
||||
* Periodically recurring task that runs continuously
|
||||
*/
|
||||
public static ScheduledFuture<?> scheduleAtFixedRate(Runnable runnable, long period, TimeUnit unit) {
|
||||
|
||||
@@ -169,7 +170,7 @@ public abstract class SchedulerBus {
|
||||
|
||||
|
||||
/**
|
||||
* 固定延迟执行的任务
|
||||
* Task executed with a fixed delay
|
||||
*/
|
||||
public static ScheduledFuture<?> schedule(Runnable runnable, long delay, TimeUnit unit) {
|
||||
|
||||
@@ -177,7 +178,7 @@ public abstract class SchedulerBus {
|
||||
}
|
||||
|
||||
/**
|
||||
* cron表达式执行的任务
|
||||
* Task triggered by a cron expression
|
||||
*/
|
||||
public static void scheduleCron(Runnable runnable, String cron) {
|
||||
if (SchedulerContext.isStop()) {
|
||||
@@ -188,7 +189,7 @@ public abstract class SchedulerBus {
|
||||
}
|
||||
|
||||
/**
|
||||
* 立刻执行的任务
|
||||
* Task executed immediately
|
||||
*/
|
||||
public static void execute(Runnable runnable) {
|
||||
executor.execute(ThreadUtils.safeRunnable(runnable));
|
||||
|
||||
@@ -22,14 +22,17 @@ import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
/**
|
||||
* SchedulerContext注入到Spring容器中的时机分析:
|
||||
* 首先运行测试工程:com.zfoo.scheduler.ApplicationTest
|
||||
* 打断点可以发现,在解析application.xml时,这种自定义的解析是在DefaultBeanDefinitionDocumentReader.java类的parseBeanDefinitions中解析xml的"scheduler元素"时
|
||||
* 发现是自定义元素(是否是spring的命名空间为依据作为判断),就会调用 parseCustomElement解析自定义标签从而调用到实现BeanDefinitionParser接口的parse方法,
|
||||
* 从而接着走自己的逻辑在spring容器中注入SchedulerContext这个bean对象。
|
||||
* Analysis of when SchedulerContext is injected into the Spring container:
|
||||
* When running the test project (com.zfoo.scheduler.ApplicationTest), breakpoints reveal that
|
||||
* during the parsing of application.xml, the custom parsing is triggered inside
|
||||
* DefaultBeanDefinitionDocumentReader#parseBeanDefinitions when the "scheduler" XML element is encountered.
|
||||
* Since it is recognized as a custom element (determined by whether it belongs to the Spring namespace),
|
||||
* parseCustomElement is called to handle the custom tag, which in turn invokes the parse() method
|
||||
* of the BeanDefinitionParser implementation, registering SchedulerContext as a bean in the Spring container.
|
||||
* <p>
|
||||
* 从而可以得出结论:在基于zfoo的SpringBoot工程中,由于压根不解析xml对象,注册bean也是通过@Configuration配置类注册bean的,
|
||||
* 因此这些实现BeanDefinitionParser接口的parse方法是都不会执行的。
|
||||
* Conclusion: In a SpringBoot project based on zfoo, XML files are not parsed at all;
|
||||
* beans are registered via @Configuration classes instead.
|
||||
* Therefore, these BeanDefinitionParser#parse() implementations are never executed.
|
||||
*
|
||||
* @author godotg
|
||||
*/
|
||||
@@ -43,7 +46,7 @@ public class SchedulerDefinitionParser implements BeanDefinitionParser {
|
||||
String name;
|
||||
BeanDefinitionBuilder builder;
|
||||
|
||||
// 注册SchedulerContext
|
||||
// Register SchedulerContext
|
||||
clazz = SchedulerContext.class;
|
||||
name = StringUtils.uncapitalize(clazz.getName());
|
||||
builder = BeanDefinitionBuilder.rootBeanDefinition(clazz);
|
||||
|
||||
@@ -27,9 +27,9 @@ public class StopWatch {
|
||||
}
|
||||
|
||||
/**
|
||||
* 从StopWatch被创建,到调用这个方法消耗的时间
|
||||
* Elapsed time from when the StopWatch was created until this method is called.
|
||||
*
|
||||
* @return 返回消耗的时间,保留两位小数,格式xx.xx
|
||||
* @return elapsed time in seconds, rounded to two decimal places (format: xx.xx)
|
||||
*/
|
||||
public String costSeconds() {
|
||||
var cost = cost() / (float) TimeUtils.MILLIS_PER_SECOND;
|
||||
|
||||
@@ -30,29 +30,29 @@ import java.util.TimeZone;
|
||||
*/
|
||||
public abstract class TimeUtils {
|
||||
|
||||
// 一秒钟对应的纳秒数
|
||||
// Nanoseconds per second
|
||||
public static final long NANO_PER_SECOND = 1_000_000_000;
|
||||
// 一秒钟对应的毫秒数
|
||||
// Milliseconds per second
|
||||
public static final long MILLIS_PER_SECOND = 1 * 1000;
|
||||
// 一分钟对应的毫秒数
|
||||
// Milliseconds per minute
|
||||
public static final long MILLIS_PER_MINUTE = 1 * 60 * MILLIS_PER_SECOND;
|
||||
// 一个小时对应的毫秒数
|
||||
// Milliseconds per hour
|
||||
public static final long MILLIS_PER_HOUR = 1 * 60 * MILLIS_PER_MINUTE;
|
||||
// 一天对应的毫秒数
|
||||
// Milliseconds per day
|
||||
public static final long MILLIS_PER_DAY = 1 * 24 * MILLIS_PER_HOUR;
|
||||
// 一周对应的毫秒数
|
||||
// Milliseconds per week
|
||||
public static final long MILLIS_PER_WEEK = 1 * 7 * MILLIS_PER_DAY;
|
||||
// 默认的时区
|
||||
// Default time zone
|
||||
public static final TimeZone DEFAULT_TIME_ZONE = TimeZone.getDefault();
|
||||
// 默认的时区Id
|
||||
// Default zone ID
|
||||
public static final ZoneId DEFAULT_ZONE_ID = TimeZone.getDefault().toZoneId();
|
||||
|
||||
|
||||
// 统一的时间格式模板
|
||||
// Standard date-time format template
|
||||
public static final String DATE_FORMAT_TEMPLATE = "yyyy-MM-dd HH:mm:ss";
|
||||
// 简单的时间格式模板
|
||||
// Simple date-time format template
|
||||
public static final String SIMPLE_DATE_FORMAT_TEMPLATE = "yyyyMMddHHmmss";
|
||||
// 统一的时间格式模板
|
||||
// Standard date-only format template
|
||||
public static final String DATE_FORMAT_TEMPLATE_FOR_DAY = "yyyy-MM-dd";
|
||||
|
||||
private static final FastThreadLocalAdapter<SimpleDateFormat> DATE_FORMAT = new FastThreadLocalAdapter<>(() -> new SimpleDateFormat(DATE_FORMAT_TEMPLATE));
|
||||
@@ -63,7 +63,7 @@ public abstract class TimeUtils {
|
||||
|
||||
static {
|
||||
currentTimeMillis();
|
||||
// 调用一下静态方法,使SchedulerBus静态代码块初始化
|
||||
// Call a static method to trigger the static initializer of SchedulerBus
|
||||
SchedulerBus.refreshMinTriggerTimestamp();
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public abstract class TimeUtils {
|
||||
private static long timestamp = System.currentTimeMillis();
|
||||
|
||||
/**
|
||||
* 获取精确的时间戳
|
||||
* Get the precise current timestamp in milliseconds
|
||||
*/
|
||||
public static long currentTimeMillis() {
|
||||
timestamp = System.currentTimeMillis();
|
||||
@@ -79,20 +79,19 @@ public abstract class TimeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* CN:获取最多只有一秒延迟的粗略时间戳,适用于对时间精度要求不高的场景,比System.currentTimeMillis()的性能高10倍
|
||||
* <p>
|
||||
* EN:Obtain a coarse timestamp with a delay of up to one second, which is suitable for scenarios that do not require high time accuracy
|
||||
* Obtain a coarse timestamp with a delay of up to one second, which is suitable for scenarios that
|
||||
* do not require high time accuracy. Its performance is 10x faster than System.currentTimeMillis().
|
||||
*/
|
||||
public static long now() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
// --------------------------------------日期格式--------------------------------------
|
||||
// -------------------------------------- Date Format --------------------------------------
|
||||
|
||||
/**
|
||||
* 把日期字符串转换成Date对象,统一的日期模板要遵循DATE_FORMAT_TEMPLATE="yyyy-MM-dd HH:mm:ss"
|
||||
* Convert a date string to a Date object. The standard date template follows DATE_FORMAT_TEMPLATE="yyyy-MM-dd HH:mm:ss"
|
||||
*
|
||||
* @param dateString 日期字符串,如:2018-02-12 10:12:50
|
||||
* @param dateString date string, e.g. 2018-02-12 10:12:50
|
||||
* @return <code>Date</code>
|
||||
*/
|
||||
public static Date stringToDate(String dateString) {
|
||||
@@ -104,9 +103,9 @@ public abstract class TimeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 把long类型的时间戳转换成字符串格式的时间
|
||||
* Convert a long timestamp to a formatted date-time string
|
||||
*
|
||||
* @param time 时间戳
|
||||
* @param time timestamp in milliseconds
|
||||
* @return yyyy-MM-dd HH:mm:ss
|
||||
*/
|
||||
public static String timeToString(long time) {
|
||||
@@ -128,7 +127,7 @@ public abstract class TimeUtils {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
// --------------------------------------日期判断--------------------------------------
|
||||
// -------------------------------------- Date Comparison --------------------------------------
|
||||
|
||||
/**
|
||||
* <p>Checks if two date objects are on the same day ignoring time.</p>
|
||||
@@ -191,10 +190,9 @@ public abstract class TimeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 判断两个日期是否是同一周,设置周一为一周的第一天
|
||||
* <p>
|
||||
* 2004-12-25”是星期六,也就是说它是2004年中第52周的星期六,那么“2004-12-26”到底是2004年的第几周哪,java中经测试取得的它的Week值是1,
|
||||
* 那么也就是说它被看作2005年的第一周了,这个处理是比较好的。可以用来判断“2004-12-26”和“2005-1-1”是同一周。
|
||||
* Check whether two timestamps fall in the same week, with Monday as the first day of the week.
|
||||
* For example, "2004-12-25" is Saturday (week 52 of 2004), while "2004-12-26" has a WEEK_OF_YEAR
|
||||
* value of 1 in Java (treated as week 1 of 2005), so "2004-12-26" and "2005-01-01" are considered the same week.
|
||||
*/
|
||||
public static boolean isSameWeek(long time1, long time2) {
|
||||
Calendar cal1 = Calendar.getInstance();
|
||||
@@ -206,13 +204,13 @@ public abstract class TimeUtils {
|
||||
|
||||
int yearDiff = cal1.get(Calendar.YEAR) - cal2.get(Calendar.YEAR);
|
||||
if (yearDiff == 0 && cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR)) {
|
||||
// yearDiff==0,说明是同一年
|
||||
// yearDiff==0 means they are in the same year
|
||||
return cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR);
|
||||
} else if (yearDiff == 1 && cal2.get(Calendar.MONTH) == 11) {
|
||||
//yearDiff==1,说明cal比cal2大一年;java的一月用"0"标识,那么12月用"11"
|
||||
// yearDiff==1 means cal1 is one year ahead of cal2; January is represented as "0" in Java, December as "11"
|
||||
return cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR);
|
||||
} else if (yearDiff == -1 && cal1.get(Calendar.MONTH) == 11) {
|
||||
//yearDiff==-1,说明cal比cal2小一年
|
||||
// yearDiff==-1 means cal1 is one year behind cal2
|
||||
return cal1.get(Calendar.WEEK_OF_YEAR) == cal2.get(Calendar.WEEK_OF_YEAR);
|
||||
}
|
||||
return false;
|
||||
@@ -227,11 +225,11 @@ public abstract class TimeUtils {
|
||||
&& cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.MONTH) == cal2.get(Calendar.MONTH);
|
||||
}
|
||||
|
||||
// --------------------------------------获取相关时间戳--------------------------------------
|
||||
// -------------------------------------- Retrieve Related Timestamps --------------------------------------
|
||||
|
||||
|
||||
/**
|
||||
* 获取给定时间戳对应的日期的0点时间戳
|
||||
* Get the timestamp of midnight (00:00:00) for the given timestamp's date
|
||||
*/
|
||||
public static long getZeroTimeOfDay(long time) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
@@ -245,7 +243,7 @@ public abstract class TimeUtils {
|
||||
|
||||
|
||||
/**
|
||||
* 获取给定时间戳对应的日期的最后时刻时间戳
|
||||
* Get the timestamp of the last moment (23:59:59.999) for the given timestamp's date
|
||||
*/
|
||||
public static long getLastTimeOfDay(long time) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
@@ -257,7 +255,7 @@ public abstract class TimeUtils {
|
||||
return cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
// 获取给定时间戳对应的日期的昨天这个时刻的时间戳
|
||||
// Get the timestamp of yesterday at the same time as the given timestamp
|
||||
public static long getYesterdayTimeOfDay(long time) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
cal.setTimeInMillis(time);
|
||||
@@ -265,35 +263,35 @@ public abstract class TimeUtils {
|
||||
return cal.getTimeInMillis();
|
||||
}
|
||||
|
||||
// 获取给定时间戳对应小时的起始时间戳
|
||||
// Get the start timestamp of the hour corresponding to the given timestamp
|
||||
public static long getStartTimeOfHour(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var monday = localDateTime.withMinute(0).withSecond(0).withNano(0);
|
||||
return TimeUtils.localDateTimeToTimestamp(monday);
|
||||
}
|
||||
|
||||
// 获取给定时间戳对应周的第一天的起始时间戳
|
||||
// Get the start timestamp of the first day of the week corresponding to the given timestamp
|
||||
public static long getStartTimeOfWeek(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var monday = localDateTime.with(TemporalAdjusters.previous(DayOfWeek.SUNDAY)).plusDays(1).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
return TimeUtils.localDateTimeToTimestamp(monday);
|
||||
}
|
||||
|
||||
// 获取给定时间戳对应月的第一天的起始时间戳
|
||||
// Get the start timestamp of the first day of the month corresponding to the given timestamp
|
||||
public static long getStartTimeOfMonth(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var oneOfMonth = localDateTime.with(TemporalAdjusters.firstDayOfMonth()).withHour(0).withMinute(0).withSecond(0).withNano(0);
|
||||
return TimeUtils.localDateTimeToTimestamp(oneOfMonth);
|
||||
}
|
||||
|
||||
// 获取给定时间戳对应月的最后一天的结束时间戳
|
||||
// Get the end timestamp of the last day of the month corresponding to the given timestamp
|
||||
public static long getEndTimeOfMonth(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var oneOfMonth = localDateTime.with(TemporalAdjusters.lastDayOfMonth()).withHour(23).withMinute(59).withSecond(59).withNano(0);
|
||||
return TimeUtils.localDateTimeToTimestamp(oneOfMonth);
|
||||
}
|
||||
|
||||
//获取上一个月月初的时间
|
||||
// Get the start timestamp of the previous month
|
||||
public static long getLastMonthStart(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var lastMonth = localDateTime.minusMonths(1);
|
||||
@@ -301,7 +299,7 @@ public abstract class TimeUtils {
|
||||
return TimeUtils.localDateTimeToTimestamp(with);
|
||||
}
|
||||
|
||||
//获取上一个月月末的时间
|
||||
// Get the end timestamp of the previous month
|
||||
public static long getLastMonthEnd(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var lastMonth = localDateTime.minusMonths(1);
|
||||
@@ -309,7 +307,7 @@ public abstract class TimeUtils {
|
||||
return TimeUtils.localDateTimeToTimestamp(with);
|
||||
}
|
||||
|
||||
//获取下一个月月初的时间
|
||||
// Get the start timestamp of the next month
|
||||
public static long getNextMonthStart(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var lastMonth = localDateTime.plusMonths(1);
|
||||
@@ -317,7 +315,7 @@ public abstract class TimeUtils {
|
||||
return TimeUtils.localDateTimeToTimestamp(with);
|
||||
}
|
||||
|
||||
// 获取下一个月月末的时间
|
||||
// Get the end timestamp of the next month
|
||||
public static long getNextMonthEnd(long time) {
|
||||
var localDateTime = TimeUtils.timestampToLocalDateTime(time);
|
||||
var lastMonth = localDateTime.plusMonths(1);
|
||||
@@ -326,10 +324,10 @@ public abstract class TimeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* LocalDateTime转毫秒时间戳
|
||||
* Convert LocalDateTime to millisecond timestamp
|
||||
*
|
||||
* @param localDateTime LocalDateTime
|
||||
* @return 时间戳
|
||||
* @return timestamp in milliseconds
|
||||
*/
|
||||
public static Long localDateTimeToTimestamp(LocalDateTime localDateTime) {
|
||||
var zoneId = ZoneId.systemDefault();
|
||||
@@ -338,9 +336,9 @@ public abstract class TimeUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* 时间戳转LocalDateTime
|
||||
* Convert millisecond timestamp to LocalDateTime
|
||||
*
|
||||
* @param timestamp 时间戳
|
||||
* @param timestamp timestamp in milliseconds
|
||||
* @return LocalDateTime
|
||||
*/
|
||||
public static LocalDateTime timestampToLocalDateTime(long timestamp) {
|
||||
@@ -349,13 +347,13 @@ public abstract class TimeUtils {
|
||||
return LocalDateTime.ofInstant(instant, zone);
|
||||
}
|
||||
|
||||
// --------------------------------------时间大小判断--------------------------------------
|
||||
// -------------------------------------- Time Comparison --------------------------------------
|
||||
public static boolean timeBetween(long time, long from, long end) {
|
||||
return from <= time && time <= end;
|
||||
}
|
||||
|
||||
|
||||
// --------------------------------------cron表达式--------------------------------------
|
||||
// -------------------------------------- Cron Expression --------------------------------------
|
||||
public static long nextTimestampByCronExpression(CronExpression expression, long currentTimestamp) {
|
||||
var zonedDateTime = ZonedDateTime.ofInstant(Instant.ofEpochMilli(currentTimestamp), DEFAULT_ZONE_ID);
|
||||
return nextTimestampByCronExpression(expression, zonedDateTime);
|
||||
|
||||
@@ -18,8 +18,8 @@ import org.junit.Test;
|
||||
import org.springframework.context.support.ClassPathXmlApplicationContext;
|
||||
|
||||
/**
|
||||
* cron(译为克龙)代表100万年,是英文单词中最大的时间单位。
|
||||
* google(译为古戈尔)代表10的100次方,足够穷尽宇宙万物
|
||||
* 'cron' means 1 million years - the largest time unit in English.
|
||||
* 'googol' represents 10 to the power of 100 - enough to enumerate all things in the universe.
|
||||
*
|
||||
* @author godotg
|
||||
*/
|
||||
@@ -28,7 +28,7 @@ public class ApplicationTest {
|
||||
|
||||
@Test
|
||||
public void startSchedulerTest() {
|
||||
// 加载配置文件,配置文件中必须引入scheduler
|
||||
// Load the configuration file (must import the scheduler module)
|
||||
var context = new ClassPathXmlApplicationContext("application.xml");
|
||||
|
||||
ThreadUtils.sleep(10000);
|
||||
|
||||
@@ -28,12 +28,12 @@ public class SchedulerController {
|
||||
|
||||
@Scheduler(cron = "0/5 * * * * ?")
|
||||
public void cronScheduler1() {
|
||||
logger.info("scheduler1 每5秒时间调度任务");
|
||||
logger.info("scheduler1 scheduled task every 5 seconds");
|
||||
}
|
||||
|
||||
@Scheduler(cron = "0,10,20,40 * * * * ?")
|
||||
public void cronScheduler2() {
|
||||
logger.info("scheduler2 每分钟的10秒,20秒,40秒调度任务");
|
||||
logger.info("scheduler2 scheduled task at second 10, 20, 40 of every minute");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -29,22 +29,22 @@ public class TimeUtilsTest {
|
||||
|
||||
@Test
|
||||
public void testLocalDate() {
|
||||
// 取当前日期:
|
||||
// Get current date:
|
||||
LocalDate today = LocalDate.now(); // -> 2014-12-24
|
||||
// 根据年月日取日期:
|
||||
// Construct date from year/month/day:
|
||||
LocalDate crischristmas = LocalDate.of(2014, 12, 25); // -> 2014-12-25
|
||||
// 根据字符串取:
|
||||
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); // 严格按照ISO yyyy-MM-dd验证,02写成2都不行,当然也有一个重载方法允许自己定义格式
|
||||
LocalDate.parse("2014-02-26"); // 无效日期无法通过:DateTimeParseException: Invalid date
|
||||
// 取本月第1天:
|
||||
// Parse from string:
|
||||
LocalDate endOfFeb = LocalDate.parse("2014-02-28"); // Strict ISO yyyy-MM-dd; overloaded methods allow custom formats
|
||||
LocalDate.parse("2014-02-26"); // Invalid date throws DateTimeParseException
|
||||
// Get first day of this month:
|
||||
LocalDate firstDayOfThisMonth = today.with(TemporalAdjusters.firstDayOfMonth()); // 2017-03-01
|
||||
// 取本月第2天:
|
||||
// Get second day of this month:
|
||||
LocalDate secondDayOfThisMonth = today.withDayOfMonth(2); // 2017-03-02
|
||||
// 取本月最后一天,再也不用计算是28,29,30还是31:
|
||||
// Get last day of this month (no manual 28/29/30/31 needed):
|
||||
LocalDate lastDayOfThisMonth = today.with(TemporalAdjusters.lastDayOfMonth()); // 2017-12-31
|
||||
// 取下一天:
|
||||
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // 变成了2018-01-01
|
||||
// 取2017年1月第一个周一,用Calendar要死掉很多脑细胞:
|
||||
// Get next day:
|
||||
LocalDate firstDayOf2015 = lastDayOfThisMonth.plusDays(1); // results in 2018-01-01
|
||||
// Get first Monday of January 2017 (much simpler than Calendar):
|
||||
LocalDate firstMondayOf2015 = LocalDate.parse("2017-01-01").with(TemporalAdjusters.firstInMonth(DayOfWeek.MONDAY)); // 2017-01-02
|
||||
}
|
||||
|
||||
@@ -59,13 +59,13 @@ public class TimeUtilsTest {
|
||||
LocalTime time = LocalTime.of(0, 0, 0);
|
||||
LocalDateTime localDateTime = LocalDateTime.of(date, time);
|
||||
System.out.println(localDateTime);
|
||||
//将localDateTime转换成时间戳
|
||||
// Convert LocalDateTime to timestamp
|
||||
System.out.println("localDateTime:" + java.sql.Timestamp.valueOf(localDateTime).getTime());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 计算周五的活动下次开启的时间
|
||||
* Calculate the next activation time for the Friday event
|
||||
*/
|
||||
@Test
|
||||
public void test() {
|
||||
|
||||
Reference in new issue
Block a user