Java使用DateTimeFormatter实现格式化时间

网友投稿 389 2022-12-16


Java使用DateTimeFormatter实现格式化时间

用扫描器获取输入的时间(年月日时分),这个时间的格式是常用的格式,然后格式化这个时间,把格式化的时间输出到控制台,可以在控制台重复输入时间.格式化的时间参考企业微信聊天记录的展示时间.用DateTimeFormatter实现,功能如下:

同年:

不同年:

同月:月日+上午/下午+时分

同年不同月:月日+时分

今天:上午/下午+时分

明天:明天+上午/下午+时分

昨天:昨天+上午/下午+时分

包括今天在内的一周内:星期+上午/下午+时分

首先看一下测试类:

package hrkj;

import java.util.Scanner;

/**

* 日期时间测试类

*

* @author 张林琛

* @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 张林琛

* @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 张林琛

* @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 张林琛

* @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 &ltcoBsTpcc;= 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(coBsTpcc).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号为星期日)没有实现,如需其他需要,请自行添加逻辑实现.


版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:Springboot打包部署代码实例
下一篇:Java 二分法检索算法代码实现详解
相关文章

 发表评论

暂时没有评论,来抢沙发吧~