时间相关
DateFormatUtils – 提供格式化日期和时间的功能及相关常量;
DateUtils – 在Calendar和Date的基础上提供更方便的访问;
DurationFormatUtils – 提供格式化时间跨度的功能及相关常量;
FastDateFormat – 为java.text.SimpleDateFormat提供一个的线程安全的替代类;
FormatCache -
StopWatch – 是一个方便的计时器。
常见名词
UTC:协调世界时(标准时间)
GMT:格林尼治标准时(世界时)
CST:美国/中国中央 (打印Date能看见),属于时区三字母id,被废了
DST夏日节约时间,北京时间等特殊时间
时间戳:1970年1月1日(08:00:00 GMT)至当前时间的总秒数,unix发行时间,也被称为 Unix 时间戳
一般我们用的是北京时间=UTC+8=GMT+8
引用:
import java.text.ParseException; // 解析时出现意外错误。 import java.text.ParsePosition; //Format 及其子类所使用的简单类 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.Iterator; //迭代器 import java.util.NoSuchElementException;//枚举中没有更多的元素
可以看到是对Date的封装,首先要简单的了解Date/Calendar/SimpleDateFormat
java.util.Date
api描述:
在 JDK 1.1 之前,类 Date
有两个其他的函数。它允许把日期解释为年、月、日、小时、分钟和秒值。它也允许格式化和解析日期字符串。不过,这些函数的 API 不易于实现国际化。从 JDK 1.1 开始,应该使用 Calendar
类实现日期和时间字段之间转换,使用 DateFormat
类来格式化和解析日期字符串。Date
中的相应方法已废弃。
尽管 Date
类打算反映协调世界时 (UTC),但无法做到如此准确,这取决于 Java 虚拟机的主机环境。当前几乎所有操作系统都假定 1 天 = 24 × 60 × 60 = 86400 秒。但对于 UTC,大约每一两年出现一次额外的一秒,称为“闰秒”。闰秒始终作为当天的最后一秒增加,并且始终在 12 月 31 日或 6 月 30 日增加。例如,1995 年的最后一分钟是 61 秒,因为增加了闰秒。大多数计算机时钟不是特别的准确,因此不能反映闰秒的差别。
补充:废除的差不多了,通常也就new Date()一下
java.util.Calendar
api描述:
Calendar
类是一个抽象类,它为特定瞬间与一组诸如 YEAR
、MONTH
、DAY_OF_MONTH
、HOUR
等 日历字段之间的转换提供了一些方法,并为操作日历字段(例如获得下星期的日期)提供了一些方法。瞬间可用毫秒值来表示,它是距历元(即格林威治标准时间 1970 年 1 月 1 日的 00:00:00.000,格里高利历)的偏移量。
补充:代替Date,改变时间也很方便,常用set/add
打印如下,可以看到完全的与样式分离(date有默认样式)
java.util.GregorianCalendar[time=1388458208688,areFieldsSet=true,areAllFieldsSet=true,lenient=true,
zone=sun.util.calendar.ZoneInfo[id="Asia/Shanghai",offset=28800000,dstSavings=0,useDaylight=false,
transitions=19,lastRule=null],firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2013,
MONTH=11,WEEK_OF_YEAR=1,WEEK_OF_MONTH=5,DAY_OF_MONTH=31,DAY_OF_YEAR=365,
DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=5,AM_PM=0,HOUR=10,HOUR_OF_DAY=10,MINUTE=50,
SECOND=8,MILLISECOND=688,ZONE_OFFSET=28800000,DST_OFFSET=0]
----------------------时间样式
java.text.DateFormat
api描述:
DateFormat 是日期/时间格式化子类的抽象类,它以与语言无关的方式格式化并解析日期或时间。日期/时间格式化子类(如 SimpleDateFormat)允许进行格式化(也就是日期 -> 文本)、解析(文本-> 日期)和标准化。将日期表示为 Date
对象,或者表示为从 GMT(格林尼治标准时间)1970 年 1 月 1 日 00:00:00 这一刻开始的毫秒数。
java.text.SimpleDateFormat
api描述:
SimpleDateFormat
是一个以与语言环境有关的方式来格式化和解析日期的具体类。它允许进行格式化(日期 -> 文本)、解析(文本 -> 日期)和规范化。
大多数情况下还是选择用SimpleDateFormat
,初始化话格式后new SimpleDateFormat("yyyyMMdd");在format(渲染/格式话)一下就完成了
DateUtils提供方法
1.判断
isSameDay:判断2时间是否为同一天
isSameInstant:判断是否为同一瞬间(比较时间戳)
isSameLocalTime:判断是否为本地时间(分别比较,且要求同一实现类)
public static boolean isSameDay(Calendar cal1, Calendar cal2) { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } return (cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && //公元前后 cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) &&//年 cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR));//第几天 }
public static boolean isSameInstant(Calendar cal1, Calendar cal2) { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } return cal1.getTime().getTime() == cal2.getTime().getTime(); //cal1.getTime()-》Date,比较的是时间戳 }
public static boolean isSameLocalTime(Calendar cal1, Calendar cal2) { if (cal1 == null || cal2 == null) { throw new IllegalArgumentException("The date must not be null"); } return (cal1.get(Calendar.MILLISECOND) == cal2.get(Calendar.MILLISECOND) && cal1.get(Calendar.SECOND) == cal2.get(Calendar.SECOND) && cal1.get(Calendar.MINUTE) == cal2.get(Calendar.MINUTE) && cal1.get(Calendar.HOUR_OF_DAY) == cal2.get(Calendar.HOUR_OF_DAY) && cal1.get(Calendar.DAY_OF_YEAR) == cal2.get(Calendar.DAY_OF_YEAR) && cal1.get(Calendar.YEAR) == cal2.get(Calendar.YEAR) && cal1.get(Calendar.ERA) == cal2.get(Calendar.ERA) && cal1.getClass() == cal2.getClass()); //同一实现类 }
2.解析 date->>text
parseDate(String str, String... parsePatterns)
parseDateStrictly(String str, String... parsePatterns)
将格式如parsePatterns的str解析为Date,其中Strictly代表严格
String[] pattern = new String[] {"yyyy-MM-dd"}; DateUtils.parseDate("2011-1-32", pattern); //Tue Feb 01 00:00:00 CST 2011 DateUtils.parseDateStrictly("2011-1-32", pattern);// throws ParseException
private static Date parseDateWithLeniency( String str, String[] parsePatterns, boolean lenient) throws ParseException { if (str == null || parsePatterns == null) { throw new IllegalArgumentException("Date and Patterns must not be null"); } SimpleDateFormat parser = new SimpleDateFormat(); parser.setLenient(lenient); //是否严格 ParsePosition pos = new ParsePosition(0); for (String parsePattern : parsePatterns) { //循环所有样式 String pattern = parsePattern; // LANG-530 - need to make sure 'ZZ' output doesn't get passed to SimpleDateFormat if (parsePattern.endsWith("ZZ")) { pattern = pattern.substring(0, pattern.length() - 1); } parser.applyPattern(pattern); pos.setIndex(0); String str2 = str; // LANG-530 - need to make sure 'ZZ' output doesn't hit SimpleDateFormat as it will ParseException if (parsePattern.endsWith("ZZ")) { str2 = str.replaceAll("([-+][0-9][0-9]):([0-9][0-9])$", "$1$2"); } Date date = parser.parse(str2, pos); if (date != null && pos.getIndex() == str2.length()) { return date; } } throw new ParseException("Unable to parse the date: " + str, -1); }
3.add系列/set系列
private static Date add(Date date, int calendarField, int amount) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } Calendar c = Calendar.getInstance(); c.setTime(date); c.add(calendarField, amount); return c.getTime(); }
private static Date set(Date date, int calendarField, int amount) { if (date == null) { throw new IllegalArgumentException("The date must not be null"); } // getInstance() returns a new object, so this method is thread safe. Calendar c = Calendar.getInstance(); c.setLenient(false);//宽松型 c.setTime(date); c.set(calendarField, amount); return c.getTime(); }
4.toCalendar:另一种创建方法
public static Calendar toCalendar(Date date) { Calendar c = Calendar.getInstance(); c.setTime(date); return c; }
5.
round(Date date, int field) :四舍五入,field为字段(泛型),精确到的值,使用了clone,线程安全
truncate(Date date, int field):全舍
ceiling(Date date, int field):全入
... if (MODIFY_TRUNCATE == modType || millisecs < 500) {//如果为truncate,就减去500毫秒在四舍五入 time = time - millisecs; } if (field == Calendar.SECOND) { done = true; } // truncate seconds int seconds = val.get(Calendar.SECOND); if (!done && (MODIFY_TRUNCATE == modType || seconds < 30)) { time = time - (seconds * 1000L); } if (field == Calendar.MINUTE) { done = true; } // truncate minutes int minutes = val.get(Calendar.MINUTE); if (!done && (MODIFY_TRUNCATE == modType || minutes < 30)) { time = time - (minutes * 60000L); } ...
6.
iterator(Date focus, int rangeStyle):根据rangeStyle返回Calendar集合范围(求一周/月等)
RANGE_MONTH_SUNDAY和RANGE_MONTH_MONDAY都是取focus所在月份一个月的天数,
RANGE_MONTH_SUNDAY每月从SUNDAY开始,
RANGE_MONTH_MONDAY每月从MONDAY开始
RANGE_WEEK_SUNDAY都是取1周(7天)的天数,
RANGE_WEEK_RELATIVE从focus开始取7天,
RANGE_WEEK_CENTER从focus所在星期的星期一开始取7天。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET 原生驾驭 AI 新基建实战系列:向量数据库的应用与畅想
· 从问题排查到源码分析:ActiveMQ消费端频繁日志刷屏的秘密
· 一次Java后端服务间歇性响应慢的问题排查记录
· dotnet 源代码生成器分析器入门
· ASP.NET Core 模型验证消息的本地化新姿势
· 开发的设计和重构,为开发效率服务
· 从零开始开发一个 MCP Server!
· .NET 原生驾驭 AI 新基建实战系列(一):向量数据库的应用与畅想
· ThreeJs-16智慧城市项目(重磅以及未来发展ai)
· Ai满嘴顺口溜,想考研?浪费我几个小时