当前位置: 首页 > 科技观察

Harmonyos开源第三方组件-日期时间处理组件JodaTime-ohos

时间:2023-03-12 03:12:30 科技观察

更多信息请访问:Harmonyos.51cto.com,与华为官方共同打造的鸿蒙技术社区序基于Android平台的日期和时间处理组件JodaTime-ohos(https://github.com/dlew/joda-time-android)实现鸿蒙迁移重构。代码已经开源(https://gitee.com/isrc_ohos/joda-time_ohos),欢迎下载使用并提出宝贵意见!背景JodaTime-ohos是一个日期时间处理组件,可以获取标准时间、当前时间、相对时间、格式化时间等多种形式的时间,支持多种类型时间的计算和判断。该组件简单易用,可扩展性强,功能集全面,支持多种日历系统,广泛应用于时间显示应用。组件效果展示(1)显示“标准时间”、“一段时间”、“格式化时间”、“一段时间的相对表示”、“一段时间的相对字符串表示”、“相对时间”Standardtime:程序执行时刻的时间表示,见图1中的a。Formattime:将日期/时间格式转换为预定义的日期/时间格式,见图1中的b。一段时间:根据程序执行时间,加上一段时间后的开始时间和结果时间,见图1中的c。一段时间的相对表示:将来或过去的某个时间段,见图1中的d图1.一段时间的相对字符串表示:在程序执行时间的基础上,加上一段结果时间显示,见图1中的e。相对时间:在程序执行时间的基础上,加上结果一段时间后的time和timeperiod,见图1中的f。图1为“标准时间”,“aperiodof时间","格式化时间","一段时间的相对表示","一段时间的相对字符串表示","相对时间"(2)显示"当前时间","是否是今天"Current时间:程序执行的年月日。同时也可以给出在当前时间的基础上加上一段时间后的结果,如图2的a是否是今天:可以判断程序执行的日期是否是今天,无论是昨天,还是明天,如图2的b所示。图2显示“当前时间”和“是否是今天”(3)显示“一段时间的格式化表示”“一段时间的格式化表示”:用相应的单位表示一段时间。图3“一段时间的格式化表示”样本分析1.项目结构图4Sample的项目结构从上图可以看出,Sample的项目结构主要分为三个部分:MainAbilitySlice部分①中figure主要负责构建组件app的主页面布局。主页上有9个按钮。点击不同的按钮会跳转到不同的导航界面。每个界面显示不同的时间格式,如图5所示。图5组件应用程序主页面布局图中②部分的内容包括多个AbilitySlice,每个AbilitySlice对应①中的一个导航界面。界面会包含一个特定格式的时间显示,如图6所示。图6Button导航界面图中③部分内容包括两个文件:MainAbility是所有应用程序的入口,通过setMainRoute()设置路由,将组件应用的主界面设置为MainAbilitySlice。JodaTime用于创建接收时区更改广播的示例。//JodaTimetry{JodaTimeAndroid.init(this);//init方法用于创建接收时区变化广播的实例}catch(RemoteExceptione){e.printStackTrace();}2.时间获取JodaTime-ohos可以为开发者提供9种不同格式的时间。下面我们以sampleGetRelativeTimeSpanStringslice为例,演示获取“一段时间的相对表示”时间。效果如上图1中的d所示。其他时间格式的使用方法相同,这里不再赘述。(1)导入相关类导入sampleGetRelativeTimeSpanStringslice中的DateTime类,获取实例化对象,即时间日期获取工具类。//导入相关类DateTimeimportorg.joda.time.DateTime;......//实例化类对象DateTimenow=DateTime.now();(2)设置时间显示布局在sampleGetRelativeTimeSpanStringslice中创建一个DirectionalLayout布局,用于显示获取到的时间。DirectionalLayoutdirectionalLayout=newDirectionalLayout(this);......@OverrideprotectedvoidonStart(Intentintent){super.onStart(intent);//设置Layout的宽高directionalLayout.setWidth(ComponentContainer.LayoutConfig.MATCH_PARENT);directionalLayout.setHeight(ComponentContainer.LayoutConfig.MATCH_PARENT);directionalLayout.setPadding(32,32,80,80);//设置Layoutpadding距离ShapeElementelement=newShapeElement();element.setRgbColor(newRgbColor(255,255,255));directionalLayout.setBackground(element);//设置Layout背景...}(3)设置时间显示控件由于布局中需要显示多个时间结果,所以这里创建一个List,内部元素为String类型,每个String元素代表一个时间结果。列表text=newArrayList();(4)获取日期时间值通过上面创建的DateTime类对象,调用类中的不同方法,如plusMinutes(),minusMinutes(),在起始时间点的基础上增加或减少一个固定时间时间;然后使用DateUtils类的getRelativeTimeSpanString()方法获取相应单位(小时、分钟或秒)的日期和时间值。text.add("Shortfuture:"+DateUtils.getRelativeTimeSpanString(this,now.plusMinutes(25)));//将分钟添加到当前时间值text.add("Mediumfuture:"+DateUtils.getRelativeTimeSpanString(this,now.plusHours(5)));//根据当前时间值添加小时text.add("Longfuture:"+DateUtils.getRelativeTimeSpanString(this,now.plusDays(3)));//根据当前时间值添加daystext.add("Shortpast:"+DateUtils.getRelativeTimeSpanString(this,now.minusMinutes(25)));//根据当前时间值减少分钟数text.add("Mediumpast:"+DateUtils.getRelativeTimeSpanString(this,now.minusHours(5)));//根据当前时间值减少小时text.add("Longpast:"+DateUtils.getRelativeTimeSpanString(this,now.minusDays(3)));//根据当前时间值减少天数(5)将控件添加到布局中将获取到的日期时间值添加到时间显示布局DirectionalLayout中。directionalLayout.addComponent(textT);3.常用的日期时间类。第2节中的示例使用DateTime来获取时间。通常,在使用JodaTime_ohos组件的过程中,使用最多的有5种日期时间获取类,分别是:Instant类、DateTime类、LocalDate类、LocalTime类和LocalDateTime类。根据要获取的日期时间值的格式不同,需要引入的类也会不同。下面简单介绍一下这几个类的作用:Instant:用来表示时间轴上的一个瞬时点,即一个事件发生的时间戳,与使用的日历系统或所在时区无关位于。DateTime类:是JodaTime_ohos的核心类,可以判断在时间轴上的位置。使用该类的时间格式包括标准时间(sampleDateTimeslice)、格式化时间(sampleFormatDateTimeslice)、时间间隔(sampleDateRangeslice)、相对时间(sampleGetRelativeDateTimeStringslice)、时间段的相对表示(sampleGetRelativeTimeSpanStringslice)、相对时间的字符串表示(sampleGetRelativeTimeSpanStringWithPrepositionslice)).LocalDate类:表示本地日期,不含时间部分,适合强调纪念日等日期。使用该类的时间格式包括当前时间(sampleLocalDatelslice)和今天时间(sampleIsTodayslice)。LocalTime:表示本地时间,不带日期部分,适用于强调时间,如上下班时间。LocalDateTime:表示本地日期和时间,适用于考试时间等同时强调日期和时间的场合。以上五个类都是不可变类。无论如何修改和处理,所有与日期和时间相关的API都会返回一个全新的JodaTime_ohos实例,类似于Java的String类。除了上述5个常用的类外,本Sample中还使用了Duration类,该类涉及的时间格式是一段时间的格式化表示(sampleFormatDurationslice)。Library将整个JodaTime-ohos组件库解析为五个部分,如图7所示。图7库组成结构JodaTimeAndroid类负责初始化相关操作。在开始使用JodaTime_ohos组件之前,需要通过该类的init()方法对其进行初始化,否则将无法正常访问组件中的类和方法;ResourceZoneInfoProvide类负责时区的监听,不过这里需要注意的是,鸿蒙并没有提示时区变化的意图;TimeZoneChangedReceiver类负责处理监听到的时区变化;DateUtils类主要负责将获取的日期时间值处理成多种格式。其中,DateUtils类是核心的时间格式处理类,是一个封装好的工具类。如图8所示,Sample中使用的日期和时间类是DateTime类、LocalDate类和Duration类。最多7种格式的日期和时间表示。图8时间格式处理核心类1.方法重载实现多种时间格式在DateUtils类中,时间格式转换的方法有很多,其中一些通过方法重载具有多种参数形式,可以在使用时根据需要传入使用不同数量的参数,可以获得不同格式的日期和时间,增加了程序的可读性。以getRelativeTimeSpanString()方法为例,该方法用于获取相对时间跨度,如“20分钟前”、“20分钟内”。通过方法重载的方式,调用该方法可以根据参数的不同得到两种类型,分别有两个参数和三个参数:(1)当两个参数为time和flags时,可以得到的时间格式是相对表示一段时间后,效果如上图1.1中的面板d所示。获取传入的原始时间值后,判断时、分、秒,完成相应的处理。publicstaticCharSequencegetRelativeTimeSpanString(Contextcontext,ReadableInstanttime,intflags)throwsNotExistException,WrongTypeException,IOException{booleanabbrevRelative=(flags&(FORMAT_ABBREV_RELATIVE|FORMAT_ABBREV_ALL))!=0;//将传入的原始时间值转换为DateTime类型DateZnowone.TimeZnow(Dtime()).withMillis(OfSe)0);//获取原始时间值...//判断时、分、秒,完成相应的处理(Hours.ONE)){...}elseif(Days.daysIn(interval).isLessThan(Days.ONE)){...}elseif(Weeks.weeksIn(interval).isLessThan(Weeks.ONE)){...}...returnString.format(format,count);//返回处理结果}(2)三个参数:当传入参数为time、flags和withPrepositon时,得到的时间格式是一个句点表示相对时间的字符串,效果如上图1.1中的图e所示。先获取传入的原始时间值,转换成LocalDate格式,然后分别判断时分秒,完成处理,返回对应的时间格式。publicstaticCharSequencegetRelativeTimeSpanString(Contextctx,ReadableInstanttime,booleanwithPreposition)throwsNotExistException,WrongTypeException,IOException{Stringresult;LocalDatenow=LocalDate.now();//实例化LocalDate对象,获取本地时间LocalDatetimeDate=newLocalDate(time);//将要返回的原始时间值传入ConverttoLocalDatetypeintprepositionId;//判断时分秒,完成处理if(Days.daysBetween(now,timeDate).getDays()==0){...}elseif(Years.yearsBetween(now,timeDate).getYears()!=0){...}else{...}if(withPreposition){result=ctx.getResourceManager().getElement(prepositionId).getString(result);}returnresult;//返回处理结果}2.在同一个方法中判断实现多种时间格式除了上述通过方法重载实现不同时间格式的情况外,还有一种方法是在DateUtils类中实现多种时间格式,也就是同样的方法,通过对不同类型的原始时间数据进行相应的判断和处理,得到不同类型的时间值。以一段时间表示的sampleFormatDurationslice类为例,效果如上图1.4所示。开发者在Sample中使用时,需要分别通过standardSeconds()、standardMinutes()、standardHours()方法获取不同的时间值,即秒、分、小时,然后调用DateUtils中的formatDuration()方法:文本。add("Seconds:"+DateUtils.formatDuration(this,Duration.standardSeconds(25)));//获取25秒的标准时间值text.add("Minutes:"+DateUtils.formatDuration(this,Duration.standardMinutes(5)));//获取5分钟的标准时间值text.add("Hours:"+DateUtils.formatDuration(this,Duration.standardHours(3)));//获取3小时的标准时间值formatDuration()方法中,如果原始时间数据中包含小时,则进行第一次判断,返回小时类型的时间处理结果;如果原始时间数据包含分钟,则进行二次判断,返回分钟类型的时间处理结果;如果原来的时间数据中包含秒,则不进入判断,直接返回秒类型的时间处理结果。publicstaticCharSequenceformatDuration(Contextcontext,ReadableDurationreadableDuration)throwsIOException,NotExistException,WrongTypeException{ResourceManagerres=context.getResourceManager();Durationduration=readableDuration.toDuration();//将传入的原始时间值转换为Duration类型finalinthours=(int)duration.getStandardHours();//获取传入的原始时间值if(hours!=0){//判断传入的时间值是否包含小时return//返回包含小时的时间值的时间格式res.getElement(net.danlew.android.joda.ResourceTable.Plural_joda_time_android_duration_hours).getPluralString(hours,hours);}finalintminutes=(int)duration.getStandardMinutes();if(minutes!=0){//判断传入的时间值是否包含分钟return//返回时间值包含时间格式的分钟res.getElement(net.danlew.android.joda.ResourceTable.Plural_joda_time_android_duration_minutes).getPluralString(minutes,minutes);}finalintseconds=(int)duration.getStandardSeconds();return//传入的时间值如果包含秒,则直接返回处理后的结果res.getElement(net.danlew.android.joda.ResourceTable.Plural_joda_time_android_duration_seconds).getPluralString(seconds,seconds);},请访问:与华为共建鸿蒙科技社区https://harmonyos.51cto.com