DateTimeFormatter(datetimeformatter注解用法)
在Java中,以下哪种定义,可以得到4位年2位月2位日,24小时制的格式()(2分?)?
LocalDateTime dateTime = LocalDateTime.now();
String str = dateTime.format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
System.out.println(str);
jdk1.8中DateTimeFormatter.ofPattern线程安全问题
你将Date对象和模板对象都做为参数传进静态方法就没有线程安全问题了
java 判断一个时间是不是今天的时间范围内
public?class?Test?{
????/**
?????*?java?判断一个时间是不是今天的时间范围内
?????*?@param?args
?????*/
????public?static?void?main(String[]?args)?{
????????String?time?=?"2017-09-27?11:20:45";
????????DateTimeFormatter?dtf?=?DateTimeFormatter.ofPattern("uuuu-MM-dd?HH:mm:ss");
????????LocalDateTime?localTime?=?LocalDateTime.parse(time,?dtf);
????????LocalDateTime?startTime?=?LocalDate.now().atTime(0,?0,?0);
????????LocalDateTime?endTime?=?LocalDate.now().atTime(23,?59,?59);
????????//如果小于今天的开始日期
????????if?(localTime.isBefore(startTime))?{
????????????System.out.println("时间是过去");
????????}
????????//如果大于今天的开始日期,小于今天的结束日期
????????if?(localTime.isAfter(startTime)??localTime.isBefore(endTime))?{
????????????System.out.println("时间是今天");
????????}
????????//如果大于今天的结束日期
????????if?(localTime.isAfter(endTime))?{
????????????System.out.println("时间是未来");
????????}
????}
}
怎样用DateTimeFormatter解决数据库中查询时间多了一个.0
数据库表add中有一个入住时间字段(如rf)。
入住时间与现在的时间差=datediff("h",rs("rf"),now())'入住到现在的时间,其中H为小时数
spring类型转换器(三)
Converter用来将源数据类型转换目标数据类型,不过有时候一个数据类型会对应不同格式的字符串,如日期类型在不同国家显示的字符是不一样的,需要根据Locale进行转换,或者需要将日期类型转换为不同格式化的字符串,spring针对这种情况提供了Formatter接口来针对格式化进行处理。
格式化Formatter其实也是一种Converter,只是两个互转类型之间, 有一个固定是String类型 ,Formatter实现了不同格式的String类型与其他类型的类型互转
Formatter主要针对的是Number类型和日期类型。Spring对这两种类型的子类和字符串之间的转换提供了格式化实现,下面以日期类型的转换为例说明。
Formatter接口继承了Printer和Parser接口,一个用于将对象格式化为本地化的字符串,一个将字符串转换为对象。
AnnotationFormatterFactory集成了注解和Formatter。可以创建带有Annotation性质的Printer和Parser对象。
在上章节的继承图中可以看到FormattingConversionService继承了GenericConversionService。同时实现了FormatterRegistry和ConverterRegistry接口
FormatterRegistry扩展了ConverterRegistry接口,额外提供了注册Formatter、AnnotationFormatterFactory的功能
FormatterRegistrar接口用于批量注册Formatter的接口
spring提供了FormattingConversionService的默认实现DefaultFormattingConversionService,使用的时候一般都是直接使用这个类。
首先来看DefaultFormattingConversionService,在BeanFactory中只接收一个ConversionService变量,所以只能给spring容易配置一个ConversionService。那么到底应该用DefaultFormattingConversionService还是用DefaultConversionService?让我们来看DefaultFormattingConversionService中的实现
从源码可以看出,DefaultFormattingConversionService完全是对DefaultConversionService的扩展,在构造函数中调用了DefaultConversionService的addDefaultConverters完全拥有了DefaultConversionService所有的功能,所以只需要使用DefaultFormattingConversionService就可以
DefaultFormattingConversionService创建完成之后除了添加Converters,还注册了一些Formatters,这些Formaters主要是spring提供的用于针对 日期类型 、 Number类型 、 货币金额 进行格式化转换
接下来分析下Formater的注册功能。通过上述分析我们可以知道,Formater实质上是Class?和String之间的互转,所以在注册的时候,只需要提供Class?、Printer和Parser。来看FormattingConversionService类中的实现
可以看到的是注册Formater的过程,就是注册了一对Converter。注册Converter的过程已经在前文分析过,在这里我们来一起看下PrinterConverter和ParserConverter类。
可以看出PrinterConverter类型实现GenericConverter,用于实现传入类型到字符串的转换,具体的转换功能委托给参数Printer实现类对象实现。这里相当于是一个插件类保留。可以通过Printer实现任何类型到String类型的转换。
再来看ParserConverter
ParserConverter跟PrinterConverter实现了一个反方向的转换,至此注册通过一个Formater接口实现类,就可以完成Formater实现类中泛型到String类型之间的互转。
例如注册 LocalDateTime的转换器,实现LocalDateTime和String类型的互转
可以看到使用一个类TemporalAccessorPrinter和TemporalAccessorParser,并都传入了一个参数DateTimeFormatter,众所周知LocalDateTime和String格式化就是通过DateTimeFormatter来实现。那么我们猜测TemporalAccessorParser其实就是对DateTimeFormatter的封装调用
可以看到TemporalAccessorPrinter就是调用的DateTimeFormatter完成格式化的,不过这里使用到了ThreadLocal,可以先不管,TemporalAccessorParser中同理也会使用DateTimeFormatter完成String到日期的转换
Formatter的注册最终是注册了一对Converter,所以格式化转换完全就是Converter逻辑的实现,在前文已经分析过了,这里就不再赘述。
分析完了Formatter的注册和转换过程,一起来看下FormatConversionService提供了另外一种注册。前文提到了可以通过在对象字段上声明一个注解,在注解中指定格式化后字符串格式。这个功能就是通过AnnotationFormatterFactory来实现的。来看FormatConversionService的 addFormatterForFieldAnnotation() 方法
AnnotationFormatterFactory的注册,首先需要获取的就是AnnotationFormatterFactory泛型中的注解类型。然后通过 getFieldTypes() 获取所有声明的可以进行转换类型集合,然后循环注册了两个类型转换器AnnotationPrinterConverter和AnnotationParserConverter。那么来看一下AnnotationPrinterConverter到底如何完成可配置的类型转换的
可以看到的是,AnnotationPrinterConverter实现了ConditionalGenericConverter接口,在 matches() 方法中声明了该转换器只会作用于Class?上有指定的注解的类型。在convert方法中最终创建了一个PrinterConverter对象,使用PrinterConverter完成格式化的功能,这个在上面已经分析过了。唯一的不同就是Printer的获取。使用annotationFormatterFactory获取printer,并将注解作为参数传递进去。所以可以我们可以实现AnnotationFormatterFactory的 getPrinter() 方法提供转换为字符串的功能即可,通过看以通过参数annotation获取用户配置的格式。实现格式的可配置。
同样在AnnotationParserConverter中实现String到Class?的转换,调用AnnotationFormatterFactory获取Parser然后创建一个ParserConverter来实现类型转化。需要注意的是 注解只能添加在非String类型那一方上。
通过封装封装注册AnnotationPrinterConverter和AnnotationParserConverter,用户需要做的就只有是实现AnnotationFormatterFactory,在泛型中指定注解,然后实现了 getPrinter() 和 getParser() 来实现Class?和String之间的转换,其他的调用直接走Converter流程。来看Date类型格式化的实现
在DateFormatterRegistrar中,在注册Formatters之前,先注册了日期类型的一些converter,这里先不去管这个。最主要的是 addFormatterForFieldAnnotation 方法,通过这个方法完成对Formater的注册
来看下DateTimeFormatAnnotationFormatterFactory实现了AnnotationFormatterFactory。并指定注解为DateTimeFormat。
可以看到的是在 getFieldType() 声明了支持转换的有Date、Calendar、Long。可以看到 getPrinter() 和 getFormatter() 方法返回了一个DateFormatter对象,并将用户配置的注解信息注入到这个DateFormatter对象中
接下来就是最终的格式化实现就是这个DateFormatter对象了。大家想一下,一般针对Date类型的格式化都会用什么呢?想必大家都猜到了,没错就是SimpleDateFormat。在DateFormatter中就是创建了一个SimpleDateFormat来实现类型和字符串的转换的
至此就实现了Formatter的注册和使用。那么在spring中是如何使用的呢?
没错就注册一个id为conversionService的FormattingConversionServiceFactoryBean对象。使用这个就可以了,不需要再注册ConversionServiceFactoryBean了。
timeformat怎么改成localtime
如何将String解析/转换为LocalTime对象? Java中是否有任何内置函数可以使我做到这一点?
推荐答案
只需使用java.time.format.DateTimeFormatter:
DateTimeFormatter parser = DateTimeFormatter.ofPattern("h[:mm]a");
LocalTime localTime = LocalTime.parse("10AM", parser);
解释模式:
h:一天中的上午/下午(从1到12),用1或2位数字
[]:可选节的定界符(其中的所有内容都是可选的)
:mm:一个:字符,后跟两位数字的分钟数
a:AM/PM的代号