通过DateTimeFormatter格式器格式化日期时间

通过DateTimeFormatter格式器格式化日期时间

题目要求:

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

知识需求

  1. java基础知识
  2. Scanner扫描器
  3. 普通类,枚举类
  4. final修饰符
  5. 正则表达式
  6. DateTimeFormatter格式器(格式化及解析知识)
  7. 包装类,打印对象
  8. 一系列的常用方法等

实现思路及简易步骤

  1. 获取扫描器,通过扫描器获取输入的时间(年月日时分)
  2. 创建一个Notice类(提示信息类),用于存取日期时间格式化期间要用到的完整的提示信息(如普通类,枚举类)
  3. 创建一个Regex枚举类,用于匹配日期时间的正则表达式,把传入的日期时间匹配相对应的正则表达式,将匹配好的日期时间传入日期时间工具类的获取日期时间的方法中,然后进行具体的格式化实现
  4. 这个时间的格式是常用的格式,然后格式化这个时间,把格式化的时间输出到控制台,可以在控制台重复输入时间.格式化的时间参考企业微信聊天记录的展示时间.
  5. 需要实现:
    同年:
    同月:月日+时分
    今天:上午/下午+时分
    明天:明天+时分
    昨天:昨天+时分
    今天之前(包括今天)的一周内:星期+时分
    不同月时:
    上个月(通过调整时间进行测试):
    今天:上午/下午+时分
    明天:明天+时分
    昨天:昨天+时分
    今天之前(包括今天)的一周内:星期+时分
    本月:月日+时分
    下个月(通过调整时间进行测试):
    明天:明天+时分
    其他月:月日+时分
    不同年:年月日+时分

程序测试情景如下:

欢迎使用日期时间格式器!
若退出程序,请输入'exit'或'退出' !
请参考企业微信聊天记录的展示时间,输入一个合法的时间:
合法时间格式为日期格式为yyyy.MM.dd HH:mm
         形如:2020.1.10 19:19
    或日期格式为yyyy-MM-dd HH:mm
         形如:2020-1-10 19:19
    或日期格式为yyyy/MM/dd HH:mm
         形如:2020/1/10 19:19
请输入:
2020/1/11 19:19
格式化后日期时间为:
          下午 19:19
若退出程序,请输入'exit'或'退出' !
2020/1/12 19:19
格式化后日期时间为:
          明天 19:19
若退出程序,请输入'exit'或'退出' !
2020/1/10 19:19
格式化后日期时间为:
          昨天 19:19
若退出程序,请输入'exit'或'退出' !
2020/1/9 19:19
格式化后日期时间为:
          周四 19:19
若退出程序,请输入'exit'或'退出' !
2020/1/3 19:19
格式化后日期时间为:
          1月3日 19:19
若退出程序,请输入'exit'或'退出' !
2020/2/29 19:19
格式化后日期时间为:
          2月29日 19:19
若退出程序,请输入'exit'或'退出' !
2019/2/28 19:19
格式化后日期时间为:
          2019年2月28日 19:19
若退出程序,请输入'exit'或'退出' !

如果需要其他情形,请自行测试!

实现代码如下:

测试类
package datetimeformatter;

/**
 * 日期时间测试类<br>
 * 2020年1月10日 上午9:43:16
 * 
 * @author zcf
 * @version 1.0
 */
public class Test {
	/**
	 * 程序入口
	 * 
	 * @param args 入口参数
	 */
	public static void main(String[] args) {
		/**
		 * 进入时间格式器
		 */
		DateTime.startIn();
	}
}
日期时间类
package datetimeformatter;

import java.util.Scanner;

/**
 * 日期时间类<br>
 * 2020年1月10日 上午9:44:13
 * 
 * @author zcf
 * @version 1.0
 */
public class DateTime {
	/**
	 * 闰年日期正则
	 */
	private static final String LEEP_YEAR = Regex.LEEP_YEAR.getDesc();

	/**
	 * 平年日期正则
	 */
	private static final String COMMON_YEAR = Regex.COMMON_YEAR.getDesc();
	/**
	 * 时间正则
	 */
	private static final String TIME = Regex.TIME.getDesc();

	/**
	 * 私有构造器 不能创建实例
	 */
	private DateTime() {

	}

	/**
	 * 时间格式器,开始方法
	 */
	public static void startIn() {
		// 进入程序的提示语
		Notice.inTip();
		// 获取扫描器
		Scanner sc = new Scanner(System.in);
		// 判断是否有下一行输入
		while (sc.hasNextLine()) {
			// 获取下一行输入输入的日期时间
			// trim()方法忽略在控制台输出时,前后的无用空格
			String dateTime = sc.nextLine().trim();
			if (dateTime.matches("exit|退出")) {
				// 退出程序
				Notice.printNotice(Notice.EXIT_FINASH);
				// 关闭扫描器
				sc.close();
				break;
			}
			// 把传入的日期时间匹配相对应的正则表达式
			else if ((dateTime.matches(LEEP_YEAR + TIME)) || (dateTime.matches(COMMON_YEAR + TIME))) {
				// 将匹配好的时间传入工具类的获取日期时间的方法中
				DateTimeTool.getDateTime(dateTime);
				// 退出程序
				Notice.printNotice(Notice.EXIT_PROGRAM);
				continue;
			} else {
				// 匹配失败,提示错误
				Notice.printNotice(Notice.DATE_TIME_ERROR);
				// 可进行退出
				Notice.printNotice(Notice.EXIT_PROGRAM);
			}
		}
	}
}
信息提示类
package datetimeformatter;

/**
 * 程序完整的提示信息<br>
 * 2020年1月10日 上午10:51:28
 * 
 * @author zcf
 * @version 1.0
 */
public class Notice {
	/**
	 * 退出程序指示语
	 */
	public static final String EXIT_PROGRAM = "若退出程序,请输入'exit'或'退出' !";
	/**
	 * 退出程序完成指示语
	 */
	public static final String EXIT_FINASH = "已退出程序,欢迎下次使用!";
	/**
	 * 日期错误指示语
	 */
	public static final String DATE_ERROR = "日期错误";
	/**
	 * 日期分隔符错误指示语
	 */
	public static final String DATE_SPLIT_ERROR = "日期分隔符错误,请重新输入:\n";
	/**
	 * 时间错误指示语
	 */
	public static final String TIME_ERROR = "时间错误";
	/**
	 * 日期时间错误指示语
	 */
	public static final String DATE_TIME_ERROR = "日期时间不合法,请重新输入:\n";

	/**
	 * 进入程序的提示语(small tip)
	 */
	public static void inTip() {
		System.out.println("欢迎使用日期时间格式器!");
		//退出程序提示语
		System.out.println(Notice.EXIT_PROGRAM);
		System.out.println("请参考企业微信聊天记录的展示时间,输入一个合法的时间:");
		System.out.println("合法时间格式为日期格式为yyyy.MM.dd HH:mm\n         形如:2020.1.10 19:19");
		System.out.println("    或日期格式为yyyy-MM-dd HH:mm\n         形如:2020-1-10 19:19");
		System.out.println("    或日期格式为yyyy/MM/dd HH:mm\n         形如:2020/1/10 19:19");
		System.out.println("请输入:");
	}

	/**
	 * 输出提示信息的方法
	 * 
	 * @param printNotice 要输出的提示信息
	 */
	public static void printNotice(String printNotice) {
		//输出提示信息
		System.out.println(printNotice);
	}
}

匹配日期时间正则表达式类
/**
	 * 验证日期格式为YYYY.MM.DD HH:MM的正则表达式 闰年,能被4整除但不能被100整除,<br>
	 * ((([0-9]{2}(0[48]|[2468][048]|[13579][26])) 闰年,能被400整除<br>
	 * |((0[48]|[2468][048]|[13579][26])00) 匹配闰年2月29日这一天。如果不是这一天,则由下面式子继续匹配验证。<br>
	 * [-\\/\\.]0?2[-\\/\\.]29 <br>
	  * 平年(0001-9999)<br>
	 * |([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})<br>
	  * 月日,1、3、5、7、8、10、12月有31天 [-\\/\\.](((0?[13578]|1[02])[-\\/\\.](0?[1-9]|[12][0-9]|3[01]))<br>
	   * 月日,4、6、9、11月有30天 |((0?[469]|11)[-\\/\\.](0?[1-9]|[12][0-9]|30)) <br>
	  * 平年2月<br>
	 * |(0?2[-\\/\\.](0?[1-9]|[1][0-9]|2[0-8])))) <br>
	  * 时间 (([01]?[0-9]|2[0-3]):[0-5]?[0-9])
	 */
package datetimeformatter;

/**
 * 时间日期匹配正则表达式<br>
 * 2020年1月10日 下午6:21:44
 * 
 * @author zcf
 * @version 1.0
 */
public enum Regex {
	/**
	 * 匹配闰年
	 */
	LEEP_YEAR("(([0-9]{2}(0[48]|[2468][048]|[13579][26]))"
			+ "|((0[48]|[2468][048]|[13579][26])00))[-\\/\\.]0?2[-\\/\\.]29"),
	/**
	 * 匹配平年
	 */
	COMMON_YEAR("|([0-9]{3}[1-9]|[0-9]{2}[1-9][0-9]{1}|[0-9]{1}[1-9][0-9]{2}|[1-9][0-9]{3})"
			+ "[-\\/\\.](((0?[13578]|1[02])[-\\/\\.](0?[1-9]|[12][0-9]|3[01]))"
			+ "|((0?[469]|11)[-\\/\\.](0?[1-9]|[12][0-9]|30))" 
			+ "|(0?2[-\\/\\.](0?[1-9]|[1][0-9]|2[0-8])))"),
	/**
	 * 匹配时间
	 */
	TIME(" (([01]?[0-9]|2[0-3]):[0-5]?[0-9])");
	/**
	 * 信息描述
	 */
	private final String desc;

	/**
	 * 有参构造器
	 * 
	 * @param desc 信息描述参数
	 */
	private Regex(String desc) {
		this.desc = desc;
	}

	/**
	 * 获取信息描述参数
	 * 
	 * @return 信息描述
	 */
	public String getDesc() {
		return desc;
	}
}
格式化日期时间类
package datetimeformatter;

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

/**
 * 日期时间工具类<br>
 * 2020年1月10日 上午11:12:19
 * 
 * @author zcf
 * @version 1.0
 */
public class DateTimeTool {
	/**
	 * 当前年
	 */
	private static int currentYear = Year.now().getValue();
	/**
	 * 当前月
	 */
	private static int currentMonth = MonthDay.now().getMonth().getValue();
	/**
	 * 当前日
	 */
	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 };

	/**
	 * 获取日期时间方法
	 * 
	 * @param dateTime 传入的日期时间
	 * @return 处理后的日期时间
	 */
	public static String getDateTime(String dateTime) {
		String result = null;
		// 通过空格来分割日期时间
		String[] dateTStrings = dateTime.split(" ");
		// 日期时间长度必须为2
		if (dateTStrings.length != 2) {
			// 日期时间错误指示语
			Notice.printNotice(Notice.DATE_TIME_ERROR);
			return Notice.DATE_TIME_ERROR;
		}
		// 分割后的日期
		String date = dateTStrings[0];
		// 分割后的时间
		String time = dateTStrings[1];
		// 分隔符
		String splitter = "";
		// 判断日期中包含的分隔符为 - . 或/
		if (date.contains("-")) {
			// 通过-分割日期
			splitter = "-";
		} else if (date.contains(".")) {
			// 通过.分割日期
			splitter = "\\.";
		} else if (date.contains("/")) {
			// 通过/分割日期
			splitter = "/";
		} else {
			return Notice.DATE_SPLIT_ERROR;
		}
		// 对传入的日期进行分割
		// 保证日期使用相同的符号分割,例如:<1>yyyy.MM.dd <2>yyyy-MM-dd <3>yyyy/MM/dd
		String[] splitAfDate = date.split(splitter);
		// 对传入的时间通过冒号(:)进行分割
		String[] splitAfTime = time.split(":");
		// 确定日期中的年月日分割符一致
		if (splitAfDate.length != 3) {
			// 分割符不一致时,返回日期错误
			System.out.println(Notice.DATE_SPLIT_ERROR);
			return Notice.DATE_SPLIT_ERROR;
		} else if (splitAfTime.length != 2) {
			// 时间错误
			System.out.println(Notice.TIME_ERROR);
			return Notice.TIME_ERROR;
		} else {
			// 分割符一致时,正常向下执行
			// 传入年
			int year = Integer.valueOf(splitAfDate[0]);
			// 传入月
			int month = Integer.valueOf(splitAfDate[1]);
			// 传入日
			int day = Integer.valueOf(splitAfDate[2]);
			// 传入时
			int hour = Integer.valueOf(splitAfTime[0]);
			// 传入分
			int minute = Integer.valueOf(splitAfTime[1]);

			// 拼接完整的日期时间
			String inDateTime = year + splitter + month + splitter + day + " " + hour + ":" + minute;
			// 使用模式字符串创建格式化器
			DateTimeFormatter formatter = DateTimeFormatter.ofPattern("y" + splitter + "M" + splitter + "d" + " H:m");
			// 把时间日期字符串解析为日期时间对象
			LocalDateTime localDateTime = LocalDateTime.parse(inDateTime, formatter);
			// 判断传入年份与当前年份一致,为同一年
			if (year == currentYear) {
				// 判断是否为同一月
				if (month == currentMonth) {
					if (day == currentDay) {
						// 今天,情景如下:
						printResult("a HH:mm", localDateTime);
					} else if (day - currentDay == 1) {
						// 明天,情景如下:
						printResult("明天 HH:mm", localDateTime);
					} else if (day - currentDay == -1) {
						// 昨天,情景如下:
						printResult("昨天 HH:mm", localDateTime);
					} else if (day - currentDay >= -7 && day - currentDay <= -2) {
						// 距今天(包括今天)的一周内,情景如下:
						printResult("E HH:mm", localDateTime);
					} else {
						// 除今天,明天,昨天,以及今天前一周的同一月,,情景如下:
						printResult("M月d日 HH:mm", localDateTime);
					}
				} else if (month - currentMonth == 1) {
					// 判断下个月
					// 判断大月小月以及平年闰年的二月
					// 传入日期为1号
					if (day == 1) {
						// 判断大月的明天
						if (Arrays.binarySearch(bigMonth, currentMonth) >= 0 && currentDay == 31) {
							// 明天,情景如下:
							printResult("明天 HH:mm", localDateTime);
							// 判断小月的明天
						} else if (Arrays.binarySearch(smallMonth, currentMonth) >= 0 && currentDay == 30) {
							// 明天,情景如下:
							printResult("明天 HH:mm", localDateTime);
						} else {
							// 二月
							if (currentMonth == 2) {
								// 判断是否为闰年
								if ((currentYear % 4 == 0 && currentYear % 100 != 0) || currentYear % 400 == 0) {
									// 闰年二月为29天
									if (currentDay == 29) {
										// 明天,情景如下:
										printResult("明天 HH:mm", localDateTime);
									} else {
										// 同月时,情景如下:
										printResult("M月d日 HH:mm", localDateTime);
									}
								} else {
									// 平年二月为28天
									if (currentDay == 28) {
										// 明天,情景如下:
										printResult("明天 HH:mm", localDateTime);
									} else {
										// 同月时,情景如下:
										printResult("M月d日 HH:mm", localDateTime);
									}
								}
							} else {
								// 同月时,情景如下:
								printResult("M月d日 HH:mm", localDateTime);
							}
						}
					} else {
						// 同月时,情景如下:
						printResult("M月d日 HH:mm", localDateTime);
					}
				} else if (month - currentMonth == -1) {
					// 判断上个月
					// 判断大月小月以及平年闰年的二月
					// 当前为1号
					if (currentDay == 1) {
						// 判断大月的昨天
						if (Arrays.binarySearch(bigMonth, month) >= 0 && day == 31) {
							// 昨天,情景如下:
							printResult("昨天 HH:mm", localDateTime);
							// 判断小月的昨天
						} else if (Arrays.binarySearch(smallMonth, month) >= 0 && day == 30) {
							// 昨天,情景如下:
							printResult("昨天 HH:mm", localDateTime);
						} else if (month == 2) {
							// 判断是否为闰年
							if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
								// 闰年二月为29天
								if (day == 29) {
									// 昨天,情景如下:
									printResult("昨天 HH:mm", localDateTime);
								}
							} else {
								// 平年二月为28天
								if (day == 28) {
									// 昨天,情景如下:
									printResult("昨天 HH:mm", localDateTime);
								}
							}
						}
						return result;
					}
					// 当前大于等于7号
					if (currentDay >= 7) {
						// 同月时,情景如下:
						printResult("M月d日 HH:mm", localDateTime);
					}
					// 当前天之前的一周
					else if (Arrays.binarySearch(bigMonth, month) >= 0 && 31 - day + currentDay < 7) {
						// 当前天以及之前的一周
						// 距今天(包括今天)的一周内,情景如下:
						printResult("E HH:mm", localDateTime);
					} else if (Arrays.binarySearch(smallMonth, month) >= 0 && 30 - day + currentDay < 7) {
						// 当前天以及之前的一周
						// 距今天(包括今天)的一周内,情景如下:
						printResult("E HH:mm", localDateTime);
					} else if (month == 2) {
						// 判断是否为闰年
						if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0) {
							// 闰年二月为29天
							if (29 - day + currentDay < 7) {
								// 当前天以及之前的一周
								// 距今天(包括今天)的一周内,情景如下:
								printResult("E HH:mm", localDateTime);
							} else {
								// 同月时,情景如下:
								printResult("M月d日 HH:mm", localDateTime);
							}
						} else {
							// 平年二月为28天
							if (28 - day + currentDay < 7) {
								// 当前天以及之前的一周
								// 距今天(包括今天)的一周内,情景如下:
								printResult("E HH:mm", localDateTime);
							} else {
								// 同月时,情景如下:
								printResult("M月d日 HH:mm", localDateTime);
							}
						}
					} else {
						// 同月时,情景如下:
						printResult("M月d日 HH:mm", localDateTime);
					}
				} else {
					// 除本月,上个月,下个月之外的不同月,情景如下:
					printResult("M月d日 HH:mm", localDateTime);
				}
			} else {
				// 不同年时,情景如下:
				printResult("yyyy年M月d日 HH:mm", localDateTime);
			}
		}
		return result;
	}

	/**
	 * 把日期时间对象格式化为日期时间字符串
	 * 
	 * @param modeString    模式字符串
	 * @param localDateTime 日期时间对象
	 */
	private static void printResult(String modeString, LocalDateTime localDateTime) {
		// 使用模式字符串创建格式化器
		DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern(modeString);
		// 把日期时间对象格式化成字符串
		String formatDateTime = formatter2.format(localDateTime);
		// 输出格式化的日期时间字符串
		System.out.println("格式化后日期时间为:\n" + "          " + formatDateTime);
	}
}

发布了4 篇原创文章 · 获赞 6 · 访问量 92

猜你喜欢

转载自blog.csdn.net/zcf_hrkj/article/details/103933148