Java使用DateTimeFormatter实现格式化时间
用扫描器获取输入的时间(年月日时分),这个时间的格式是常用的格式,然后格式化这个时间,把格式化的时间输出到控制台,可以在控制台重复输入时间.格式化的时间参考企业微信聊天记录的展示时间.用datetimeformatter实现,功能如下:
同年:
不同年:
同月:月日+上午/下午+时分
同年不同月:月日+时分
今天:上午/下午+时分
明天:明天+上午/下午+时分
昨天:昨天+上午/下午+时分
包括今天在内的一周内:星期+上午/下午+时分
首先看一下测试类:
package hrkj; import java.util.scanner; /** * 日期时间测试类 * * @author 张林琛<br> * @date 2020/01/10 08:35:29 * @version 1.0 */ public class datetimetest { public static void main(string[] args) { // 获取scanner扫描器 scanner sc = new scanner(system.in); // 程序开始提示语句 hint.hint_star.print(); // 程序退出提示语句 system.out.println(order.order_exit.getname()); while (sc.hasnextline()) { string str = sc.nextline(); // 判断是否为退出指令 if (order.order_exit.compare(str)) { hint.hint_end.print(); //如果退出,则关闭扫描器 sc.close(); break; // 判断输入的是否为空格或回车 } else if (str.equals(" ") || str.equals("" + "")) { hint.blank_or_enter.print(); } else { // 开始处理日期时间 datetimetool.datetimeformatter(str); } hint.hint_star.print(); system.out.println(order.order_exit.getname()); } } }
这里比较好的一点就是,在程序结束之前,会关闭扫描器,程序开始和程序结束,都会有提示语句:
请输入正确的时间,例如:
2020-01-10 10:10 2020.01.10 10:10 2020/01/10 10:10
退出请输入:[exit, 退出]
上面效果分别对应以下两行代码:
// 程序开始提示语句 hint.hint_star.print(); // 程序退出提示语句 system.out.println(order.order_exit.getname());
其中[exit, 退出]单独为第二行代码,与第一行代码效果拼接在一起,值得注意的是,hint是一个枚举类,程序开始;运行期间和结尾的提示语句,都定义为枚举值,具体如下:
package hrkj; /** * 日期时间类的提示语句,用于提示错误信息 * * @author 张林琛<br> * @date 2020/01/10 08:39:27 * @version 1.0 */ public enum hint { /** * 日期时间长度不合法 */ length_illegal("日期时间长度不合法,"), /** * 日期错误 */ hint_date("日期输入错误,"), /** * 月份输入不合法 */ hint_month("月份输入不合法,"), /** * 大月只有31天 */ hint_bigmonth("大月只有31天,"), /** * 小月只有30天 */ hint_tinymonth("小月只有30天,"), /** * 平年2月只有28天 */ hint_tiny_twomonth("平年二月只有28天,"), /** * 闰年二月只有29天 */ hint_big_twomonth("闰年二月只有28天,"), /** * 时间错误 */ hint_time("时间输入错误,"), /** * 输入空格或回车 */ blank_or_enter("不能输入空格或直接回车,"), /** * 以空格分开日期和时间 */ date_blank_time("请以空格分割开日期和时间,"), /** * 开始提示语句 */ hint_star("请输入正确的时间,例如:\n2020-01-10 10:10 2020.01.10 10:10 2020/01/10 10:10\n退出请输入:"), /** * 程序结束提示语句 */ hint_end("程序结束,欢迎下次使用!"); // 定义实例变量 private final string name; /** * 单个参数构造器 * * @param name */ private hint(string name) { this.name = name; } /** * 获取实例变量的值 * * @return name */ public string getname() { return name; } /** * 打印提示语句的方法 */ public void print() { system.out.print(name); } }
因为枚举类中定义了一个print()方法,调用此方法可直接打印枚举值.
上面说到,[exit, 退出]为退出指令,用户输入exit或退出则会关闭扫描器,接着关闭程序,在此也把退出定义为一个指令枚举类,具体实现如下:
package hrkj; import java.util.arrays; /** * 日期时间类的指令集,用于输入相对应的指令 * * @author 张林琛<br> * @date 2020/01/10 08:38:05 * @version 1.0 */ public enum order { /** * 退出指令 */ order_exit("exit","退出"); // 定义实例变量数组name private final string[] name; /** * 形参可变的构造器 * @param name */ private order(string... name) { this.name = name; } /** * 获取退出的指令 * @return 获取的指令 */ public string getname() { return arrays.tostring(name); } /** * 判断输入的是不是退出的指令 * @param str 输入的指令 * @return 是否是退出指令 */ public boolean compare(string str) { for (int i = 0; i < name.length; i++) { if (str.equals(name[i])) { return true; } } return false; } }
order枚举类虽然枚举实例只有一个退出(如果有其他指令可继续添加),但枚举值为两个:退出和exit,用户输入任意一个就会达到退出的效果,在此类中定义一个比较方法,用于比较用户输入的是否与枚举值相同,用到equals()方法,之所以没有用contains()方法,是因为一旦用contains()方法,那么用户输入e,x,it,等,只要是在枚举值包含的,都可以退出.
最后便是工具类,用于格式化日期时间并输出,实现细节如下
package hrkj; import java.time.localdatetime; import java.time.monthday; import java.time.year; import java.time.format.datetimeformatter; import java.time.format.formatstyle; import java.util.arrays; /** * 日期时间实现类,使用datetimeformatter实现 * * @author 张林琛<br> * @date 2020/01/10 08:36:37 * @version 1.0 */ public class datetimetool { /** * 有31天的月份 */ static int[] bigmonth = { 1, 3, 5, 7, 8, 10, 12 }; /** * 有30天的月份 */ static int[] tinymonth = { 4, 6, 9, 11 }; /** * 处理日期和时间 * * @param str */ public static void datetimeformatter(string str) { // 判断日期时间的长度 if (str.length() < 9 || str.length() > 16) { hint.length_illegal.print(); return; } // 判断输入的日期和时间是否以空格分割 if (str.contains(" ")) { // 创建数组来接收分割后的日期时间 string[] datetime = str.split(" "); // 获取日期 string[] date = splitdate(datetime[0]); // 判断日期长度 if (date.length != 3) { hint.hint_date.print(); return; } // 获取年 integer y = integer.valueof(date[0]); // 获取月 integer m = integer.valueof(date[1]); // 获取日 integer d = integer.valueof(date[2]); // 判断是不是闰年 if (!handledate(y, m, d)) { // 如果月份大于12或小于1 if (m > 12 || m < 1) { hint.hint_month.print(); return; // 如果大月天数超过31或小于1 } else if (arrays.binarysearch(bigmonth, m) > -1 && (d <= 0 || d > 31)) { hint.hint_bigmonth.print(); return; // 如果小月天数超过30或小于1 } else if (arrays.binarysearch(tinymonth, m) > -1 && (d <= 0 || d > 30)) { hint.hint_tinymonth.print(); return; // 如果平年二月天数超过28或小于1 } else if (y % 4 != 0 && y % 100 != 0 && m == 2 && (d <= 0 || d > 28)) { hint.hint_tiny_twomonth.print(); return; // 如果平年二月天数超过28或小于1 } else if (y % 400 != 0 && m == 2 && (d <= 0 || d > 28)) { hint.hint_tiny_twomonth.print(); return; // 如果闰年二月天数超过29或小于1 } else if (y % 4 == 0 && y % 100 != 0 && m == 2 && (d <= 0 || d > 29)) { hint.hint_big_twomonth.print(); return; // 如果闰年二月天数超过29或小于1 } else if (y % 400 == 0 && m == 2 && (d <= 0 || d > 29)) { hint.hint_big_twomonth.print(); return; } else { return; } } // 获取时间 string time = datetime[1]; // 判断是否以正则分割 boolean b = spilttime(time); // 如果没有以正则分割 if (!b) { hint.hint_time.print(); return; } else { // 进行日期和时间的拼接 string datetime = y + "-" + m + "-" + d + " " + time; datetimeformatter ofpattern1 = datetimeformatter.ofpattern("y-m-d h:m"); localdatetime parse1 = localdatetime.parse(datetime, ofpattern1); // system.out.println(parse1); // 判断是不是当年 if (y == year.now().getvalue()) { // 判断是不是当月 if (m == monthday.now().getmonthvalue()) { // 判断是不是今天 if (d == monthday.now().getdayofmonth()) { printmessage("今天 a h:m", parse1); // 判断是不是昨天 } else if (d - monthday.now().getdayofmonth() == -1) { printmessage("今天 a h:m", parse1); // 判断是不是明天 } else if (d - monthday.now().getdayofmonth() == 1) { printmessage("明天 a h:m", parse1); // 判断一周内的哪一天 } else if (d - monthday.now().getdayofmonth() >= -7 && d - monthday.now().getdayofmonth() <= -2) { printmessage("e a h:m", parse1); // 在当月内,但不在本周 } else { printmessage("m-d a h:m", parse1); } // 当前年的其他月 } else { printmessage("m-d h:m", parse1); } // 不同年的情况下 } else { datetimeformatter dtf = datetimeformatter.oflocalizeddatetime(formatstyle.long, formatstyle.short); system.out.println(parse1.format(dtf) + "分"); } } } else { return; } } /** * 获取时间格式器并解析,打印时间 * * @param info 模式字符串 * @param localdatetime localdatetime对象 */ private static void printmessage(string info, localdatetime localdatetime) { //把模式字符串传进去,获取到datetimeformatter对象 datetimeformatter ofpattern2 = datetimeformatter.ofpattern(info); //用localdatetime对象解析获取到的datetimeformatter对象 system.out.println(localdatetime.format(ofpattern2)); } /** * 判断大小闰年方法 * 其中判断了平年和闰年内大月和小月的天数 * @param y 年 * @param m 月 * @param d 日 * @return true为闰年,false为平年 */ private static boolean handledate(int y, int m, int d) { // 是闰年二月情况下 if (y % 4 == 0 && y % 100 != 0 && m == 2 && (d > 0 && d <= 29)) { return true; // 是闰年二月情况下 } else if (y % 400 == 0 && m == 2 && (d > 0 && d <= 29)) { return true; // 不是闰年,但是二月情况下 } else if (y % 4 != 0 && y % 400 != 0 && m == 2 && (d > 0 && d <= 28)) { // 不是闰年,2月28天 return true; // 不是二月,判断是否是大月 } else if (arrays.binarysearch(bigmonth, m) > -1 && (d > 0 && d <= 31)) { return true; // 不是二月,判断是否是小月 } else if (arrays.binarysearch(tinymonth, m) > -1 && (d > 0 && d <= 30)) { return true; } return false; } /** * 使用正则表达式限定时间 * * @param time 需要分割的时间 * @return 分割后的结果 */ private static boolean spilttime(string time) { string t = "([01]?[0-9]{1}|[2][0-3]):[0-5]?[0-9]"; return time.matches(t) ? true : false; } /** * 使用正则表达式限定日期 * * @param date 需要分割的日期 * @return 分割后的日期 */ private static string[] splitdate(string date) { // 分割年月日 string r = "[\\./-]{1}"; // 月份出现的位数 string s = "\\d{1,2}"; return date.matches("\\d+" + "(" + r + s + "){2}") ? date.split(r) : new string[0]; } }
在实现类中,使用了正则表达式(一个强大的字符串处理工具)来限定日期和时间的分隔符(. / - : 四种),输入类型(只能为数字)等,得到自己想要的日期时间格式,然后对平闰年进行判断,完成后再拼接时间.然后把获取时间格式器和解析抽象成一个方法(因为用的很多,如果不抽象成方法,会显得代码很冗长),每次使用直接调用方法.最后在不同年的情况下,使用了不同风格的时间格式化器完成格式化.
测试虽然没有任何bug,但跨年(比如19年的12月31号是20年的1月1号的昨天),跨月(比如20年1月31号为星期五,2月2号为星期日)没有实现,如需其他需要,请自行添加逻辑实现.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
上一篇: InnoDB意向锁和插入意向锁
下一篇: 怎么用JS来判断设备是pc还是移动的?
推荐阅读
-
Java之使用链表实现队列
-
使用java.util.Timer实现任务调度
-
使用java实现http多线程断点下载文件(二)
-
使用JAVA通过ARP欺骗类似P2P终结者实现数据封包监听
-
使用java实现http多线程断点下载文件(一)
-
详解java中的深拷贝和浅拷贝(clone()方法的重写、使用序列化实现真正的深拷贝)
-
Java日期时间API系列12-----Jdk8中java.time包中的新的日期时间API类,日期格式化,常用日期格式大全
-
使用Jquery+Ajax+Json如何实现分页显示附JAVA+JQuery实现异步分页
-
java使用this调用构造函数的实现方法示例
-
使用java语言实现八皇后问题