Java使用DateTimeFormatter实现格式化时间
用扫描器获取输入的时间(年月日时分),这个时间的格式是常用的格式,然后格式化这个时间,把格式化的时间输出到控制台,可以在控制台重复输入时间.格式化的时间参考企业微信聊天记录的展示时间.用DateTimeFormatter实现,功能如下:
同年:
不同年:
同月:月日+上午/下午+时分
同年不同月:月日+时分
今天:上午/下午+时分
明天:明天+上午/下午+时分
昨天:昨天+上午/下午+时分
包括今天在内的一周内:星期+上午/下午+时分
首先看一下测试类:
packagehrkj; importjava.util.Scanner; /** *日期时间测试类 * *@author张林琛
*@date2020/01/1008:35:29 *@version1.0 */ publicclassDateTimeTest{ publicstaticvoidmain(String[]args){ //获取Scanner扫描器 Scannersc=newScanner(System.in); //程序开始提示语句 Hint.HINT_STAR.print(); //程序退出提示语句 System.out.println(Order.ORDER_EXIT.getname()); while(sc.hasNextLine()){ Stringstr=sc.nextLine(); //判断是否为退出指令 if(Order.ORDER_EXIT.compare(str)){ Hint.HINT_END.print(); //如果退出,则关闭扫描器 sc.close(); break; //判断输入的是否为空格或回车 }elseif(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-1010:10 2020.01.1010:10 2020/01/1010:10
退出请输入:[exit,退出]
上面效果分别对应以下两行代码:
//程序开始提示语句 Hint.HINT_STAR.print(); //程序退出提示语句 System.out.println(Order.ORDER_EXIT.getname());
其中[exit,退出]单独为第二行代码,与第一行代码效果拼接在一起,值得注意的是,Hint是一个枚举类,程序开始;运行期间和结尾的提示语句,都定义为枚举值,具体如下:
packagehrkj; /** *日期时间类的提示语句,用于提示错误信息 * *@author张林琛
*@date2020/01/1008:39:27 *@version1.0 */ publicenumHint{ /** *日期时间长度不合法 */ 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-1010:102020.01.1010:102020/01/1010:10\n退出请输入:"), /** *程序结束提示语句 */ HINT_END("程序结束,欢迎下次使用!"); //定义实例变量 privatefinalStringname; /** *单个参数构造器 * *@paramname */ privateHint(Stringname){ this.name=name; } /** *获取实例变量的值 * *@returnname */ publicStringgetName(){ returnname; } /** *打印提示语句的方法 */ publicvoidprint(){ System.out.print(name); } }
因为枚举类中定义了一个print()方法,调用此方法可直接打印枚举值.
上面说到,[exit,退出]为退出指令,用户输入exit或退出则会关闭扫描器,接着关闭程序,在此也把退出定义为一个指令枚举类,具体实现如下:
packagehrkj; importjava.util.Arrays; /** *日期时间类的指令集,用于输入相对应的指令 * *@author张林琛
*@date2020/01/1008:38:05 *@version1.0 */ publicenumOrder{ /** *退出指令 */ ORDER_EXIT("exit","退出"); //定义实例变量数组name privatefinalString[]name; /** *形参可变的构造器 *@paramname */ privateOrder(String...name){ this.name=name; } /** *获取退出的指令 *@return获取的指令 */ publicStringgetname(){ returnArrays.toString(name); } /** *判断输入的是不是退出的指令 *@paramstr输入的指令 *@return是否是退出指令 */ publicbooleancompare(Stringstr){ for(inti=0;iOrder枚举类虽然枚举实例只有一个退出(如果有其他指令可继续添加),但枚举值为两个:退出和exit,用户输入任意一个就会达到退出的效果,在此类中定义一个比较方法,用于比较用户输入的是否与枚举值相同,用到equals()方法,之所以没有用contains()方法,是因为一旦用contains()方法,那么用户输入e,x,it,等,只要是在枚举值包含的,都可以退出.
最后便是工具类,用于格式化日期时间并输出,实现细节如下
packagehrkj; importjava.time.LocalDateTime; importjava.time.MonthDay; importjava.time.Year; importjava.time.format.DateTimeFormatter; importjava.time.format.FormatStyle; importjava.util.Arrays; /** *日期时间实现类,使用DateTimeFormatter实现 * *@author张林琛
*@date2020/01/1008:36:37 *@version1.0 */ publicclassDateTimeTool{ /** *有31天的月份 */ staticint[]bigMonth={1,3,5,7,8,10,12}; /** *有30天的月份 */ staticint[]tinyMonth={4,6,9,11}; /** *处理日期和时间 * *@paramstr */ publicstaticvoiddateTimeFormatter(Stringstr){ //判断日期时间的长度 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; } //获取年 Integery=Integer.valueOf(date[0]); //获取月 IntegerM=Integer.valueOf(date[1]); //获取日 Integerd=Integer.valueOf(date[2]); //判断是不是闰年 if(!handleDate(y,M,d)){ //如果月份大于12或小于1 if(M>12||M<1){ Hint.HINT_MONTH.print(); return; //如果大月天数超过31或小于1 }elseif(Arrays.binarySearch(bigMonth,M)>-1&&(d<=0||d>31)){ Hint.HINT_BIGMONTH.print(); return; //如果小月天数超过30或小于1 }elseif(Arrays.binarySearch(tinyMonth,M)>-1&&(d<=0||d>30)){ Hint.HINT_TINYMONTH.print(); return; //如果平年二月天数超过28或小于1 }elseif(y%4!=0&&y%100!=0&&M==2&&(d<=0||d>28)){ Hint.HINT_TINY_TWOMONTH.print(); return; //如果平年二月天数超过28或小于1 }elseif(y%400!=0&&M==2&&(d<=0||d>28)){ Hint.HINT_TINY_TWOMONTH.print(); return; //如果闰年二月天数超过29或小于1 }elseif(y%4==0&&y%100!=0&&M==2&&(d<=0||d>29)){ Hint.HINT_BIG_TWOMONTH.print(); return; //如果闰年二月天数超过29或小于1 }elseif(y%400==0&&M==2&&(d<=0||d>29)){ Hint.HINT_BIG_TWOMONTH.print(); return; }else{ return; } } //获取时间 Stringtime=datetime[1]; //判断是否以正则分割 booleanb=spiltTime(time); //如果没有以正则分割 if(!b){ Hint.HINT_TIME.print(); return; }else{ //进行日期和时间的拼接 StringdateTime=y+"-"+M+"-"+d+""+time; DateTimeFormatterofPattern1=DateTimeFormatter.ofPattern("y-M-dH:m"); LocalDateTimeparse1=LocalDateTime.parse(dateTime,ofPattern1); //System.out.println(parse1); //判断是不是当年 if(y==Year.now().getValue()){ //判断是不是当月 if(M==MonthDay.now().getMonthValue()){ //判断是不是今天 if(d==MonthDay.now().getDayOfMonth()){ printMessage("今天aH:m",parse1); //判断是不是昨天 }elseif(d-MonthDay.now().getDayOfMonth()==-1){ printMessage("今天aH:m",parse1); //判断是不是明天 }elseif(d-MonthDay.now().getDayOfMonth()==1){ printMessage("明天aH:m",parse1); //判断一周内的哪一天 }elseif(d-MonthDay.now().getDayOfMonth()>=-7 &&d-MonthDay.now().getDayOfMonth()<=-2){ printMessage("EaH:m",parse1); //在当月内,但不在本周 }else{ printMessage("M-daH:m",parse1); } //当前年的其他月 }else{ printMessage("M-dH:m",parse1); } //不同年的情况下 }else{ DateTimeFormatterdtf=DateTimeFormatter.ofLocalizedDateTime(FormatStyle.LONG,FormatStyle.SHORT); System.out.println(parse1.format(dtf)+"分"); } } }else{ return; } } /** *获取时间格式器并解析,打印时间 * *@paraminfo模式字符串 *@paramlocalDateTimeLocalDateTime对象 */ privatestaticvoidprintMessage(Stringinfo,LocalDateTimelocalDateTime){ //把模式字符串传进去,获取到DateTimeFormatter对象 DateTimeFormatterofPattern2=DateTimeFormatter.ofPattern(info); //用LocalDateTime对象解析获取到的DateTimeFormatter对象 System.out.println(localDateTime.format(ofPattern2)); } /** *判断大小闰年方法 *其中判断了平年和闰年内大月和小月的天数 *@paramy年 *@paramm月 *@paramd日 *@returntrue为闰年,false为平年 */ privatestaticbooleanhandleDate(inty,intm,intd){ //是闰年二月情况下 if(y%4==0&&y%100!=0&&m==2&&(d>0&&d<=29)){ returntrue; //是闰年二月情况下 }elseif(y%400==0&&m==2&&(d>0&&d<=29)){ returntrue; //不是闰年,但是二月情况下 }elseif(y%4!=0&&y%400!=0&&m==2&&(d>0&&d<=28)){ //不是闰年,2月28天 returntrue; //不是二月,判断是否是大月 }elseif(Arrays.binarySearch(bigMonth,m)>-1&&(d>0&&d<=31)){ returntrue; //不是二月,判断是否是小月 }elseif(Arrays.binarySearch(tinyMonth,m)>-1&&(d>0&&d<=30)){ returntrue; } returnfalse; } /** *使用正则表达式限定时间 * *@paramtime需要分割的时间 *@return分割后的结果 */ privatestaticbooleanspiltTime(Stringtime){ Stringt="([01]?[0-9]{1}|[2][0-3]):[0-5]?[0-9]"; returntime.matches(t)?true:false; } /** *使用正则表达式限定日期 * *@paramdate需要分割的日期 *@return分割后的日期 */ privatestaticString[]splitDate(Stringdate){ //分割年月日 Stringr="[\\./-]{1}"; //月份出现的位数 Strings="\\d{1,2}"; returndate.matches("\\d+"+"("+r+s+"){2}")?date.split(r):newString[0]; } }在实现类中,使用了正则表达式(一个强大的字符串处理工具)来限定日期和时间的分隔符(./-:四种),输入类型(只能为数字)等,得到自己想要的日期时间格式,然后对平闰年进行判断,完成后再拼接时间.然后把获取时间格式器和解析抽象成一个方法(因为用的很多,如果不抽象成方法,会显得代码很冗长),每次使用直接调用方法.最后在不同年的情况下,使用了不同风格的时间格式化器完成格式化.
测试虽然没有任何Bug,但跨年(比如19年的12月31号是20年的1月1号的昨天),跨月(比如20年1月31号为星期五,2月2号为星期日)没有实现,如需其他需要,请自行添加逻辑实现.
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。