使用DateTimeFormatter格式化输入的日期时间

使用DateTimeFormatter格式化输入的日期时间

要求:

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

分析:

  • 1.时间的常用格式为:

xxxx-xx-xx xx:xx
xxxx/xx/xx xx:xx
xxxx.xx.xx xx:xx
等格式

  • 2.微信显式时间格式为:

今天显式: 00:01 - 23:59 ;
昨天显式: 昨天 01:01 ;
前天显式: 周几 02:02
往前推一周都显式: 周几 02:02 ;
时间再往前推只显示: 几月几日 02:02
不同年则显式: 几年几月几日 02:02
也可考虑写一个明天显式: 明天 02:02
其余时间显式: 几月几日 02:02

  • 3.考虑特殊情况下的日期:

比如当前天是1号
则上个月的最后一天是昨天
往前推一周则显式:星期几 02:02
如果当前天不大于7号
则向前推一周到了上个月
也要考虑将其转换为星期

  • 4.先输入一个时间,再对这个时间使用DateTimeFormatter进行格式化

比如:
输入: 2020-1-11 12:22
则格式化结果为:
下午 12:22

代码实现

程序开始:
package hrkj.chapter7.dateTimeFormatter.Test1;

/**
 * 程序开始入口 <br>
 * 2020年1月9日下午7:10:04
 * 
 * @author wcf
 * @version 1.0
 */
public class Test {
	/**
	 * 程序入口
	 * 
	 * @param args 入口参数
	 */
	public static void main(String[] args) {
		// 程序开始运行
		DateTimeFormatterTest.inoutDateTime();
	}
}
日期时间等需要用到的正则表达式:
package hrkj.chapter7.dateTimeFormatter.Test1;

/**
 * 日期时间的正则表达式 <br>
 * 2020年1月9日下午7:25:11
 * 
 * @author wcf
 * @version 1.0
 */
public enum Regex {
	/**
	 * 匹配闰年
	 */
	LEEP_YEAR("((\\d{2}(0[48]|[2468][048]|[13579][26]))|((0[48]|[2468][048]|[13579][26])00))[-\\/\\.]0?2[-\\/\\.]29"),
	/**
	 * 匹配平年
	 */
	COMMON_YEAR("(\\d{3}[1-9]|\\d{2}[1-9]\\d|\\d[1-9]\\d{2}|[1-9]\\d{3})[-\\/\\.]((0?[13578]|1[02])[-\\/\\.](0?[1-9]|[12]\\d|3[01])|((0?[469]|11)[-\\/\\.](0?[1-9]|[12]\\d|30))|(0?2[-\\/\\.](0?[1-9]|1\\d|2[0-8])))"),
	/**
	 * 匹配时间
	 */
	TIME(" ([01]?\\d|2[0-3]):[0-5]?\\d"),
	/**
	 * 退出程序
	 */
	EXIT("exit|退出");

	/**
	 * 正则
	 */
	private final String str;

	/**
	 * 有参构造器
	 * 
	 * @param string 正则
	 */
	private Regex(String string) {
		this.str = string;
	}

	/**
	 * 获取正则
	 * 
	 * @return 正则
	 */
	public String getStr() {
		return str;
	}
}
提示信息:
package hrkj.chapter7.dateTimeFormatter.Test1;

/**
 * 提示信息 <br>
 * 2020年1月9日下午7:25:53
 * 
 * @author wcf
 * @version 1.0
 */
public enum Hint {
	/**
	 * 请输入日期时间
	 */
	INPUT_DATE_TIME("请输入日期时间:"),
	/**
	 * 日期时间格式
	 */
	DATETIMEFORMAT("常用格式:xxxx-xx-xx xx:xx\n\t xxxx/xx/xx xx:xx\n\t xxxx.xx.xx xx:xx"),
	/**
	 * 日期错误
	 */
	INVOKE_DATE("日期错误"),
	/**
	 * 时间错误
	 */
	INVOKE_TIME("时间错误"),
	/**
	 * 日期时间错误
	 */
	INVOKE_DATE_TIME("日期时间错误!"),
	/**
	 * 继续或退出
	 */
	CONTINUE_OR_QUIT("exit:程序退出\n请输入:"),
	/**
	 * 程序结束
	 */
	END_OF_PROGRAM("退出成功,程序结束!");

	/**
	 * 提示
	 */
	private final String str;

	/**
	 * 有参构造器
	 * 
	 * @param str 提示
	 */
	private Hint(String str) {
		this.str = str;
	}

	/**
	 * 获取提示
	 */
	public void println() {
		System.out.println(str);
	}

}

日期时间格式化的模板字符串:
package hrkj.chapter7.dateTimeFormatter.Test1;

/**
 * 日期时间格式化的模板字符串 <br>
 * 2019年3月1日下午7:17:19
 * 
 * @author wcf
 * @version 1.0
 */
public enum Pattern {
	
	/**
	 * 上下午时分
	 */
	TIME("a HH:mm"),
	/**
	 * 昨天 时分
	 */
	YESTERDAY("昨天 HH:mm"),
	/**
	 * 明天 时分
	 */
	TOMORROW("明天 HH:mm"),
	/**
	 * 星期 时分
	 */
	WEEK_TIME("E HH:mm"),
	/**
	 * 月日时分
	 */
	MONTH_DAY_TIME("M月d日 HH:mm"),
	/**
	 * 年月日时分
	 */
	YEAR_MONTH_DAY_TIME("y年M月d日 HH:mm");

	/**
	 * 显式模式
	 */
	private final String str;

	/**
	 * 有参数构造器
	 * 
	 * @param str 模式
	 */
	private Pattern(String str) {
		this.str = str;
	}

	/**
	 * 获取显式模式
	 * 
	 * @return 显式模式
	 */
	public String getStr() {
		return str;
	}

}
输入日期时间进行处理:
package hrkj.chapter7.dateTimeFormatter.Test1;

import java.util.Scanner;

/**
 * 输入日期时间进行处理 <br>
 * 2020年1月9日下午7:09:31
 * 
 * @author wcf
 * @version 1.0
 */
public class DateTimeFormatterTest {

	/**
	 * 闰年正则
	 */
	private final static String LEEP_YEAR = Regex.LEEP_YEAR.getStr();
	/**
	 * 平年正则
	 */
	private final static String COMMON_YEAR = Regex.COMMON_YEAR.getStr();
	/**
	 * 时间正则
	 */
	private final static String TIME = Regex.TIME.getStr();
	/**
	 * 退出正则
	 */
	private final static String EXIT = Regex.EXIT.getStr();

	/**
	 * 静态初始化块
	 */
	static {
		// 输入提示
		Hint.INPUT_DATE_TIME.println();
		// 日期时间格式
		Hint.DATETIMEFORMAT.println();
		// 退出指令
		Hint.CONTINUE_OR_QUIT.println();
	}
	/**
	 * 私有构造器
	 */
	private DateTimeFormatterTest() {
		// 私有构造器
		// 无法创建本类实例
	}
	/**
	 * 输入日期时间
	 */
	public static void inoutDateTime() {
		// 扫描器
		Scanner scanner = new Scanner(System.in);
		// 扫描控制台输入
		while (scanner.hasNextLine()) {
			// 接收控制台输入,并去除输入前后的空格
			String str = scanner.nextLine().trim();
			// 对输入的字符进行判断
			if (str.matches(EXIT)) {
				// 程序退出
				Hint.END_OF_PROGRAM.println();
				// 关闭扫描器
				scanner.close();
				// 退出虚拟机
				System.exit(0);
				// 判断平闰年
			} else if (str.matches(LEEP_YEAR + TIME) || str.matches(COMMON_YEAR + TIME)) {
				// 对输入的日期时间字符串进行格式化
				DateTimeFormatterTools.format(str);
				// 格式化后提示
				Hint.CONTINUE_OR_QUIT.println();
			} else {
				// 输入的日期时间不正确
				Hint.INVOKE_DATE_TIME.println();
				// 输入提示
				Hint.INPUT_DATE_TIME.println();
				continue;
			}
		}
	}
}
对输入的日期时间进行处理:
package hrkj.chapter7.dateTimeFormatter.Test1;

import java.time.LocalDateTime;
import java.time.MonthDay;
import java.time.Year;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;

/**
 * 对输入的日期时间进行处理 <br>
 * 2020年1月9日下午8:08:45
 * 
 * @author wcf
 * @version 1.0
 */
public class DateTimeFormatterTools {
	/**
	 * 年月日 时分
	 */
	private static final String YEAR_MONTH_DAY_TIME = Pattern.YEAR_MONTH_DAY_TIME.getStr();
	/**
	 * 月日 时分
	 */
	private static final String MONTH_DAY_TIME = Pattern.MONTH_DAY_TIME.getStr();
	/**
	 * 星期 时分
	 */
	private static final String WEEK_TIME = Pattern.WEEK_TIME.getStr();
	/**
	 * 上下午 时分
	 */
	private static final  String TIME = Pattern.TIME.getStr();
	/**
	 * 昨天 时分
	 */
	private static final String YESTERDAY = Pattern.YESTERDAY.getStr();
	/**
	 * 明天 时分
	 */
	private static final String TOMORROW = Pattern.TOMORROW.getStr();
	/**
	 * 当前年
	 */
	private static int currentYear = Year.now().getValue();
	/**
	 * 当前月
	 */
	private static int currentMonth = MonthDay.now().getMonthValue();
	/**
	 * 当前日
	 */
	private static int currentDay = MonthDay.now().getDayOfMonth();
	/**
	 * 大月
	 */
	private static int[] bigMonth = { 1, 3, 5, 7, 8, 10, 12 };
	/**
	 * 小月
	 */
	private static int[] smallMonth = { 4, 6, 9, 11 };

	/**
	 * 私有构造器
	 */
	private DateTimeFormatterTools() {
		// 私有构造器,无法实例化
	}

	/**
	 * 处理输入的日期时间
	 * 
	 * @param str 输入的日期时间
	 */
	public static void format(String str) {
		// 将日期和时间用空格进行分割
		String[] datetime = str.split(" ");
		// 分割成的日期
		String date = datetime[0];
		// 分割成的时间
		String time = datetime[1];
		// 日期分割方式
		String splitter = "";
		// 日期可以用- . / 进行分割
		// 如果包含了-./这三种中的一种,则用这些进行分割
		if (date.contains(".")) {
			splitter = "\\.";
		} else if (date.contains("-")) {
			splitter = "-";
		} else if (date.contains("/")) {
			splitter = "/";
		}
		// 使用日期的分割方式对日期进行分割
		String[] dateString = date.split(splitter);
		// 使用:对时间进行分割,时间只能用:进行分割
		String[] timeString = time.split(":");
		// 时间分割后的数组长度不是2则错误,因为输入的的时间只有时和分
		if (timeString.length != 2) {
			// 时间错误
			Hint.INVOKE_TIME.println();
			return;
		}
		// 日期分割后的数组长度不是3则错误,因为输入的日期要有年,月和日
		if (dateString.length != 3) {
			// 日期错误
			Hint.INVOKE_DATE.println();
			return;
		}
		// 输入的年
		int year = Integer.valueOf(dateString[0]);
		// 输入的月
		int month = Integer.valueOf(dateString[1]);
		// 输入的日
		int day = Integer.valueOf(dateString[2]);
		// 输入的时
		int hour = Integer.valueOf(timeString[0]);
		// 输入的分
		int minute = Integer.valueOf(timeString[1]);
		// 对拆解判断过的字符串进行重新组合
		String str1 = year + splitter + month + splitter + day + " " + hour + ":" + minute;
		// 对组合后的字符串进行解析
		DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern("y" + splitter + "M" + splitter + "d" + " H:m");
		// 将字符串解析成日期时间对象
		LocalDateTime parse = LocalDateTime.parse(str1, ofPattern);
		// 同一年
		if (year == currentYear) {
			// 同一月
			if (month == currentMonth) {
				// 同一天
				if (day == currentDay) {
					// 今天
					printDateTime(TIME, parse);
				} else if (day - currentDay == 1) {
					// 明天
					printDateTime(TOMORROW, parse);
				} else if (day - currentDay == -1) {
					// 昨天
					printDateTime(YESTERDAY, parse);
				} else if (day - currentDay >= -7 && day - currentDay <= -2) {
					// 向前一周以星期来表示
					printDateTime(WEEK_TIME, parse);
				} else {
					// 不同天
					printDateTime(MONTH_DAY_TIME, parse);
				}
				// 下个月
			} else if (month - currentMonth == 1) {
				// 如果输入的日是1,则判断当前月和天
				if (day == 1) {
					// 判断是大月小月还是二月,如果当前天数是月份最后一天,则输出明天
					if (Arrays.binarySearch(bigMonth, currentMonth) >= 0 && currentDay == 31) {
						// 明天
						printDateTime(TOMORROW, parse);
						return;
					} else if (Arrays.binarySearch(smallMonth, currentMonth) >= 0 && currentDay == 30) {
						// 明天
						printDateTime(TOMORROW, parse);
						return;
					} else if (currentMonth == 2) {
						// 判断输入的是闰年还是平年
						if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
							if (currentDay == 29) {
								// 明天
								printDateTime(TOMORROW, parse);
								return;
							}
						} else {
							if (currentDay == 28) {
								// 明天
								printDateTime(TOMORROW, parse);
								return;
							}
						}
					} else {
						// 使用月日进行输出
						printDateTime(MONTH_DAY_TIME, parse);
					}
				} else {
					// 输入的日不是1,这输出月日时分
					printDateTime(MONTH_DAY_TIME, parse);
				}
				// 上一月
			} else if (month - currentMonth == -1) {
				// 如果当前日是1,则判断输入日是否是上月最后一天
				if (currentDay == 1) {
					// 判断是大月小月还是二月,输入的天数是不是月份的最后一天,是则是昨天
					if (Arrays.binarySearch(bigMonth, month) >= 0 && day == 31) {
						// 昨天
						printDateTime(YESTERDAY, parse);
						return;
					} else if (Arrays.binarySearch(smallMonth, month) >= 0 && day == 30) {
						// 昨天
						printDateTime(YESTERDAY, parse);
						return;
					} else if (month == 2) {
						// 判断是闰年还是平年
						if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
							if (day == 29) {
								// 昨天
								printDateTime(YESTERDAY, parse);
								return;
							}
						} else {
							if (day == 28) {
								// 昨天
								printDateTime(YESTERDAY, parse);
								return;
							}
						}
					}
				}
				// 如果当前日不小于7,则输入月日时分,小于7则从当前天往前一周转换为星期
				if (currentDay >= 7) {
					// 输出月日时分
					printDateTime(MONTH_DAY_TIME, parse);
					// 如果当前天小于7,则当前天向前一周转换为星期
				} else if (Arrays.binarySearch(bigMonth, month) >= 0 && 31 - day + currentDay < 7) {
					// 年月日转换为星期
					printDateTime(WEEK_TIME, parse);
				} else if (Arrays.binarySearch(smallMonth, month) >= 0 && 30 - day + currentDay < 7) {
					// 年月日转换为星期
					printDateTime(WEEK_TIME, parse);
				} else if (month == 2) {
					// 判断是闰年还是平年
					if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
						if (29 - day + currentDay < 7) {
							// 年月日转换为星期
							printDateTime(WEEK_TIME, parse);
						} else {
							// 如果向前超出了一周输出月日时分
							printDateTime(MONTH_DAY_TIME, parse);
						}
					} else {
						if (28 - day + currentDay < 7) {
							// 年月日转换为星期
							printDateTime(WEEK_TIME, parse);
						} else {
							// 如果向前超出了一周输出月日时分
							printDateTime(MONTH_DAY_TIME, parse);
						}
					}
				} else {
					// 当前天向前超出了一周输出月日时分
					printDateTime(MONTH_DAY_TIME, parse);
				}
			} else {
				// 不同月,输出月日时分
				printDateTime(MONTH_DAY_TIME, parse);
			}
		} else {
			// 不同年,输出年月日时分
			printDateTime(YEAR_MONTH_DAY_TIME, parse);
		}
	}

	/**
	 * 格式化结果
	 * 
	 * @param pattern  模式字符串
	 * @param datetime 时间
	 */
	private static void printDateTime(String pattern, LocalDateTime datetime) {
		// 通过模式字符串对时间进行格式化
		DateTimeFormatter ofPattern = DateTimeFormatter.ofPattern(pattern);
		// 打印格式化后的时间
		System.out.println("格式化结果:\n\t" + ofPattern.format(datetime));
	}

}
代码测试结果:
请输入日期时间:
常用格式:xxxx-xx-xx xx:xx
	 	xxxx/xx/xx xx:xx
	 	xxxx.xx.xx xx:xx
exit:程序退出
请输入:
2020-1-11 12:22
格式化结果:
	下午 12:22
exit:程序退出
请输入:
2020-1-11 2:22
格式化结果:
	上午 02:22
exit:程序退出
请输入:
2020-1-10 1:22
格式化结果:
	昨天 01:22
exit:程序退出
请输入:
2020-1-7 12:22
格式化结果:
	周二 12:22
exit:程序退出
请输入:
2020-1-12 12:22
格式化结果:
	明天 12:22
exit:程序退出
请输入:
2020-1-13 12:22
格式化结果:
	1月13日 12:22
exit:程序退出
请输入:
2020-2-22 12:22
格式化结果:
	2月22日 12:22
exit:程序退出
请输入:
2019-12-31 12:22
格式化结果:
	2019年12月31日 12:22
exit:程序退出
请输入:

更多情况测试,或者代码简化,请自行探索测试

使用DateTimeFormatter格式化输入的日期时间使用DateTimeFormatter格式化输入的日期时间 wcf_hrkj 发布了4 篇原创文章 · 获赞 5 · 访问量 105 私信 关注
上一篇:Java 之 JDK 1.8 新增日期时间类型


下一篇:Date以及LocalDateTime格式化