用扫描器获取输入的时间(年月日时分),这个时间的格式是常用的格式,然后格式化这个时间,把格式化的时间输出到控制台,可以在控制台重复输入时间.格式化的时间参考企业微信聊天记录的展示时间.用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","退出");// 定义实例变量数组nameprivate 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或小于1if (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号为星期日)没有实现,如需其他需要,请自行添加逻辑实现.

使用DateTimeFormatter实现格式化时间相关推荐

  1. 日期格式化为yyyymmdd_你还在用SimpleDateFormat格式化时间嘛

    Jdk1.8之时间处理 该文章已经同步到Github:https://github.com/stackInk/makerstack 1. 传统时间处理的问题 1.1 多线程环境下的SimpleDate ...

  2. java 时间格式化_还在用SimpleDateFormat格式化时间?小心经理锤你

    还在用SimpleDateFormat格式化时间?小心经理锤你 场景 本来开开心心的周末时光,线上突然就疯狂报错,以为程序炸了,截停日志,发现是就是类似下述一段错误 java.lang.NumberF ...

  3. 4hutool源码分析:DateUtil(时间工具类)-格式化时间(万字长文源码分析,学大佬如何写代码)

    技术活,该赏 点赞再看,养成习惯 看本篇文章前,建议先对java源码的日期和时间有一定的了解,如果不了解的话,可以先看这篇文章: 万字博文教你搞懂java源码的日期和时间相关用法 关联文章: huto ...

  4. java 表达式 日期加减_jdk8获取当前时间|时间加减|java8时间格式化|时间处理工具|时间比较|线程安全的时间处理方法...

    目录 前言 在很久之前,我总结了一些jdk7版本之前的关于时间处理的一些公共方法,日期转换成字符串.指定时间加上指定天数后的日期.获取上周周一时间 等等:具体的可以戳链接查看完整的:https://b ...

  5. python 格式化时间

    1. 使用time 格式化时间: location = time.strftime("%Y%m%d%H%M%S" , time.localtime() ) logging.info ...

  6. 在SpringMVC中使用Jackson并格式化时间

    在spring MVC 3中,要实现REST风格的JSON服务,最简单的方式是使用 @ResponseBody 注解.该注解会自动把返回的对象,序列化为JSON. 来看一个最简单的例子.这个例子先使用 ...

  7. C语言strftime()函数 (格式化时间)(注意第二个参数size_t maxsize一定要大于第三个参数const char *format指向字符串的长度)

    需包含:C 标准库 - <time.h> 文章目录 描述 声明 参数 返回值 实例 使用☞坑(注意第二个参数size_t maxsize一定要大于第三个参数const char *form ...

  8. C语言如何返回格式化日期时间(格式化时间)?(将日期和时间以字符串格式输出)ctime()、asctime()、localtime()、strftime()

    文章目录 ctime()函数: asctime()函数 获取自定义格式化时间(有bug,当时间为个位数时,没有在前面自动补零) 改成函数接口形式(传入字符指针) 20220107 优化后(能自动补零) ...

  9. python 如何获取系统当前时间?datetime.datetime.now() 打印格式化时间(可用作文件名的格式化时间strftime)

    import datetime print(datetime.datetime.now()) 结果: 2020-02-29 16:05:06.377711 参考文章:python 如何获取当前时间 2 ...

最新文章

  1. java 序列化慢_java原生序列化慢在哪里?
  2. Uncaught TypeError: Cannot read property ‘events‘ of undefined
  3. Ajax -get 请求
  4. Scala模式匹配:变量声明中的模式匹配
  5. IPhone 应用程序管理
  6. android应用崩溃的调试方法
  7. java 邮件模板_Spring Boot 2发送邮件手把手图文教程
  8. html给背景架渐变,JS和CSS实现渐变背景特效的代码
  9. 普中科技51单片机_【笔记】普中科技-51单片机-静态数码管显示
  10. html5媒体查询的特点,巧妙使用CSS媒体查询(Media Queries)和JavaScript判断浏览器设备类型的好方法...
  11. xbox win10测试软件,win10中自带的录屏工具xbox录屏软件怎使用?
  12. 介绍打印机脱机的四种恢复方法
  13. 6.4.2.时序逻辑测试模块
  14. 计算机视觉编程 BOF图像检索(Python)
  15. LSD-slam算法原理
  16. 快速删除node_modules(rimraf)
  17. 2008Noip解题报告
  18. 百格活动独家推出执行者晋升管理层的必备指南——《活动执行手册-思维篇》
  19. C语言BCC异或效验
  20. excel里面怎么排名次

热门文章

  1. VXLAN+EVPN控制平面和数据平面交互过程分析
  2. 北大旁听生中的历史名人
  3. column分栏布局和等高布局和双飞翼布局和圣杯布局
  4. 服务器安全软件--服务器安全狗windows V4.2枸杞版发布
  5. ASP.net MVC5 简介
  6. 指针与数组——你真的懂么?
  7. 在 Raspberry Pi (树莓派) 上安装 CMake
  8. 区块链大本营的定位宣言——让区块链回归技术和应用的本质
  9. SDL基本原理及使用实战
  10. 面试官问 ,Mybatis SELECT 查询, 集合或者单个对象,如果数据库不存在数据,需要判空吗?