Java实用经验总结--日期、数字篇
1. 日期部分
对于像日期、时间和钱这样的对象来说,不同的国家、地区都有不同的显示格式。即便是同一地区,也可能存在差异。但是在不考虑国家化,时间格式相对固定的情形下,对于时间的处理还是相对比较简单的。在我最近所作的一个小程序里面,遇到了一些与日期有关的且不考虑国际化和复杂格式的问题。例如如何求两个日期所差的天数,所差的月数;将日期类转化为规定格式的字符串,将规定格式的日期字符串转成相应的日期类等等。下面我就以源码的形式逐一介绍上面提到的问题,需要注意的是这些代码都源于我做的一个名为DateUtil的类,其中独立的变量都是其中的成员变量,函数都是其成员函数:
1.1.成员变量简介:
要想对日期进行格式化首先就需要一个DateFormat类的实例,如果没有特殊需求的话,SimpleDateFormat类就是一个不错的选择,它可以将日期类格式化为在其构造函数中指定的日期格式。例如,如果我们想要将日期格式化为类似于2007-07-25这样的格式,我们就可以如下定义:
/**以yyyy-MM-dd的形式显示格式 **/
SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd");
SimpleDateFormat sFullFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
这里需要注意的是指定的日期格式一定要是”yyyy-MM-dd”,而不能是”YYYY-MM-DD”,否则的就不能正常显示。对于这个问题我没有深究,如果有对这个问题有研究的朋友欢迎留言。
下面的两个成员变量分别是日期分隔符字符串和字符串分隔器,专门用来解析字符串格式的日期。
/**
*程序中主要的日期分隔符为"-"和"/",且日期序列为“年/月/日”型,其内容缺一不可
* 例如:09/02/02或2009-02-02
**/
publicstaticfinal String DATE_SEPARATOR ="-/";
/**作日期分析之用*/
static StringTokenizer sToken;
1.2.取得两个日期之间所差天数的方法
鉴于java.util.Date类的绝大多数方法都不建议使用了,所以我也就不能够利用Date里面方便的getYear(),getMonth(),getDay()方法来计算日期差了—现在的JRE都可以自动升级,谁知道哪天SUN突然把Date这些API去掉了,那我就欲哭无泪了。不过话又说回来就算是能够使用这些方法,我们似乎也不太好算,因为每个月的日期数都不一样,如果单纯用两个日期的年月日信息来计算日期差还真是有些麻烦。基于以上两点原因,我在我的程序里采用了GregorianCalendar做为日期计算的主力军。这个类有一些很实用的方法,如get(int),这个方法可以获得当前日期类的各项日期指标。比如我们有一个日期类名为gcDate,要获取它所在的年,月,日,至需要这么做:gcDate.get(Calendar.YEAR), gcDate.get(Calendar.MONTH)以及gcDate.get(Calendar.DATE)。不过由于使用这种方法获得的日期和月份都是日期类所指定的年份的,所以如果我们知道两个日期在同一年份的话才能使用gcDate1.get(Calendar.DATE)- gcDate2.get(Calendar.DATE)来获得日期差,否则就不能这么做。
所以如果想要获得不在同一年份的日期差的话就需要用到另一个有用的方法:GregorianCalendar.add(int, int),这个方法可以让我们在日期类指定的日期指标(如年,月,日等)上加上一个数字,这个数字可以是正数也可以为负数。 其中第一个参数指定所要增加的指标,第二个参数指定增加的数量。例如我们调用gcDate.add(Calendar.DATE,1)的话,如果gcDate原来代表的时间为2007-07-24,那么调用之后就变成2007-07-25了。于是我们就可以这样计算日期差:让日期比较小的那个日期用add函数逐渐“逼近”那个较大的日期,直到两个日期完全相等为止。计数器中包含的数量即为两个日期的差值。
下面我给出了多个的计算日期差的方法,主要包含两个版本,一个版本参数为格式化字符串,另一个版本参数为GregorianCalendar。功能包括计算“今天与未来的某一天之间的日期差”和“给定两个日期的日期差”。主要的计算集中在最后一个daysBetween函数上,该函数接受两个GregorianCalendar类作为参数,并可以计算出两个日期之间的日期差,如果用户给出的较大的日期和较小的日期顺序颠倒的话,该函数会返回一个负数值。
/**
*返回未来的某一天和今天所差的日期数
*注意,这里要clone一个新的日期以免对原始日期类造成的修改。
*而在daysBetween(GregorianCalendarpFormer,GregorianCalendarpLatter)就
*直接处理而不进行clone动作,因为这里已经做了:)
**/
publicstaticint daysBetween(GregorianCalendar pFurtherDay){
GregorianCalendar vToday = new GregorianCalendar();
GregorianCalendar vFurtherDay = (GregorianCalendar) pFurtherDay.clone();
return daysBetween(vToday,vFurtherDay);
}
/**上面函数的String版本 **/
publicstaticint daysBetween(String pFurtherDayStr){
GregorianCalendar vFurtherDay = DateUtil.parse2Cal(pFurtherDayStr);
GregorianCalendar vToday = new GregorianCalendar();
return daysBetween(vToday,vFurtherDay);
}
/**返回较晚的时间(latter)与较早的时间(former)所差的天数**/
publicstaticint daysBetween(String pFormerStr,String pLatterStr){
GregorianCalendar pFormer = DateUtil.parse2Cal(pFormerStr);
GregorianCalendar pLatter = DateUtil.parse2Cal(pLatterStr);
return daysBetween(pFormer,pLatter);
}
/**返回较晚的时间(latter)与较早的时间(former)所差的天数**/
publicstaticint daysBetween(GregorianCalendar pFormer,GregorianCalendar pLatter){
GregorianCalendar vFormer = pFormer,vLatter = pLatter;
boolean vPositive = true;
if( pFormer.before(pLatter) ){
vFormer = pFormer;
vLatter = pLatter;
}else{
vFormer = pLatter;
vLatter = pFormer;
vPositive = false;
}
vFormer.set(Calendar.MILLISECOND,0);
vFormer.set(Calendar.SECOND,0);
vFormer.set(Calendar.MINUTE,0);
vFormer.set(Calendar.HOUR_OF_DAY,0);
vLatter.set(Calendar.MILLISECOND,0);
vLatter.set(Calendar.SECOND,0);
vLatter.set(Calendar.MINUTE,0);
vLatter.set(Calendar.HOUR_OF_DAY,0);
int vCounter = 0;
while(vFormer.before(vLatter)){
vFormer.add(Calendar.DATE, 1);
vCounter++;
}
if( vPositive)
return vCounter;
else
return -vCounter;
}
1.3.两个日期的月份差
获得两个日期的月份差的方法与获得日期差基本一致。但需要注意的是,计算月份差不能简单用before()来进行计算。还需要考虑到他们的年份及月份是否同时相等,只有在这种情况下,才能获得月份差的正确数值。下面同样给出了月份差的两个版本的多个函数,与日期差基本一致,这里就不再赘述。
/**
*给定两个时间相差的月数
*/
//本月和未来一个月的月份差
publicstaticint monthsBetween(GregorianCalendar pFurtherMonth){
GregorianCalendar vToday = new GregorianCalendar();
GregorianCalendar vFurtherMonth = (GregorianCalendar) pFurtherMonth.clone();
return monthsBetween(vToday,vFurtherMonth);
}
/**给定月分和本月的月份差**/
publicstaticint monthsBetween(String pFurtherMonth){
GregorianCalendar vToday = new GregorianCalendar();
GregorianCalendar vFurtherMonth = DateUtil.parse2Cal(pFurtherMonth);
return monthsBetween(vToday,vFurtherMonth);
}
/**给定两个时间相差的月数,String版**/
publicstaticint monthsBetween(String pFormerStr,String pLatterStr){
GregorianCalendar vFormer = DateUtil.parse2Cal(pFormerStr);
GregorianCalendar vLatter = DateUtil.parse2Cal(pLatterStr);
return monthsBetween(vFormer,vLatter);
}
publicstaticint monthsBetween(GregorianCalendar pFormer,GregorianCalendar pLatter){
GregorianCalendar vFormer = pFormer,vLatter = pLatter;
boolean vPositive = true;
if( pFormer.before(pLatter) ){
vFormer = pFormer;
vLatter = pLatter;
}else{
vFormer = pLatter;
vLatter = pFormer;
vPositive = false;
}
int vCounter = 0;
while(vFormer.get(vFormer.YEAR) != vLatter.get(vLatter.YEAR) ||
vFormer.get(vFormer.MONTH) != vLatter.get(vLatter.MONTH)){
vFormer.add(Calendar.MONTH, 1);
vCounter++;
}
if( vPositive)
return vCounter;
else
return -vCounter;
}
1.4.格式转换
将日期类转换成制定格式的字符串只需要调用DateFormat.format()即可。而反过来就比较麻烦,我们需要对字符串进行分析,找出其年,月,日的值分别为何,然后再用GregorianCalendar(vYear,vMonth,vDayOfMonth)构建一个新的日期类。
/** 将日期变为字符串格式 **/
publicstatic String format(GregorianCalendar pCal){
returnsDateFormat.format(pCal.getTime());
}
publicstatic String format(Date pDate){
returnsDateFormat.format(pDate);
}
publicstatic String fullFormat(Date pDate){
returnsFullFormat.format(pDate);
}
/**将字符串格式的日期转换为Calender**/
publicstatic GregorianCalendar parse2Cal(String pDateStr){
sToken = new StringTokenizer(pDateStr,DATE_SEPARATOR);
int vYear = Integer.parseInt(sToken.nextToken());
//GregorianCalendar的月份是从0开始算起的,变态!!
int vMonth = Integer.parseInt(sToken.nextToken())-1;
int vDayOfMonth = Integer.parseInt(sToken.nextToken());
returnnew GregorianCalendar(vYear,vMonth,vDayOfMonth);
}
/**将字符串类型的日期(yyyy-MM-dd)转换成Date**/
publicstatic Date parse2Date(String pDate){
try {
returnsDateFormat.parse(pDate);
}catch(ParseException ex) {
returnnull;
}
}
1.5.其他
这部分主要是一些常用方法的包装,包括获得今天是本月的第几天,本月是本年的第几个月,获得给定字符串日期的月份数,以及获得下面这个月份区间[本月,本月+pZoneSize]里的月份列表。即如果本月为6月,pZoneSize=6,则获得的月份列表应该为{6,7,8,9,10,11,12}
/**返回今天是本月的第几天**/
publicstaticint dayOfMonthOfToday(){
GregorianCalendar vTodayCal = new GregorianCalendar();
return vTodayCal.get(vTodayCal.DAY_OF_MONTH);
}
/**返回本月是本年的第几个月**/
publicstaticint monthOfYear(){
GregorianCalendar vTodayCal = new GregorianCalendar();
return vTodayCal.get(vTodayCal.MONTH)+1;
}
//返回给定日期的月份
publicstatic String getMonth(String pFormattedDate){
StringTokenizer vSt = new StringTokenizer(pFormattedDate,"-");
vSt.nextToken();//跳过年份
int val = Integer.parseInt(vSt.nextToken());
return val+"";
}
/**获得从本月开始到本月+pZoneSize区间内的月数**/
publicstatic String[] monthList(int pZoneSize){
String[] vMonthList = new String[pZoneSize];
GregorianCalendar vTodayCal = new GregorianCalendar();
for(int i = 0; i < pZoneSize; i++){
vMonthList[i] = String.valueOf(vTodayCal.get(vTodayCal.MONTH)+1);
vTodayCal.roll(vTodayCal.MONTH,true);
}
return vMonthList;
}
2. 数字部分:
这一部分我的工作比较简单,首先是格式化给定的Double变量,让其只显示两位小数。其次是由于我所做的程序付款额都是以万作为单位的,所以在必要的时候将其转为以万为单位的,带有两位小数的数字。由于比较简单,这里就不多说,各位看代码就好:
/**仅显示小数点后两位的Formater**/
publicstatic DecimalFormat formatter = new DecimalFormat("####.##");
/**将给定的数字变成小数点后两位的字符串**/
publicstatic String format(double pSrcVal){
returnformatter.format(pSrcVal);
}
/**将原始数据除以10000所得的结果**/
publicstatic String fromat2Myriad(double pSrcVal){
returnformatter.format(pSrcVal/10000.0);
}
/**将原始数据除以10000所得的结果**/
publicstatic String fromat2Myriad(String pSrcVal){
returnformatter.format(Double.parseDouble(pSrcVal)/10000.0);
}
/**将给定的数字保留两位小数返回**/
publicstaticdouble format2Double(double pSrcVal){
return (double)Math.round(pSrcVal*100)/100.0;
}
分享到:
相关推荐
【Java 实验报告 - 简单计算器程序】 在本次Java实验报告中,我们将构建一个基本的图形用户界面(GUI)计算器程序。该程序允许用户通过点击数字和运算符按钮来执行基本的数学运算,包括加法、减法、乘法、除法、...
总结,Hutool作为一款优秀的Java工具库,以其全面的功能、简洁的API和高效的性能,为Java开发者带来了极大的便利。无论你是初学者还是经验丰富的开发者,Hutool都值得你拥有。通过学习和使用Hutool,你将能够更好地...
总结来说,这个资料包提供了使用Java POI操作Excel所需的基本库和学习资源,无论是新手还是有一定经验的开发者,都能从中受益,提高处理Excel文件的能力。通过实践和研究提供的代码,你可以深入理解POI API的用法,...
在`MyOwnToolClass.java`这个文件中,我们可以期待看到以下一些常见的实用功能: 1. **字符串处理**:字符串操作在编程中极为常见,`MyOwnToolClass`可能包含了诸如检查空字符串、格式化输出、去除两端空白字符、...
Lang Utils还包括其他一些实用工具,如BooleanUtils处理布尔值,NumberUtils处理数字,RandomUtils生成随机数,StringUtils操作字符串,以及ObjectUtils处理对象等。每个工具类都精心设计,旨在解决特定问题,提升...
这篇总结将主要聚焦于Lotus Domino这一历史悠久的企业级应用平台。Lotus Domino是由IBM开发的一种服务器软件,主要用于协同工作、电子邮件、文档管理以及应用程序开发。它以其强大的数据库功能和自包含的工作流引擎...
本篇报告聚焦于一款基于Java语言开发的时钟与日历应用,旨在满足用户对于时间管理和日程规划的需求。该应用充分利用了Swing组件库,构建出一个可视化界面,同时涉及到多线程等核心编程概念。 一、系统概述 1.1 ...
- **Free Test**: 开放式的测试方法,允许测试人员根据个人经验和判断自由探索。 **2.5 测试相关文档说明** - **测试计划**: 描述测试的目的、范围、方法和资源分配。 - **测试用例**: 明确每个测试步骤及其期望...
- **教育改革需求:** 当前教育体系中,传统的教学方式已不能满足现代化教育的需求,需要借助数字化工具来提升教学质量。 - **资源共享需求:** 在线教育平台能够有效促进教育资源的共享,尤其是在计算机科学领域,...
### Lucene in Action 电子版知识点总结 #### 一、Lucene简介 - **书籍概述**:“Lucene in Action”是一本深入介绍Apache Lucene的书籍,由Otis Gospodnetic和Erik Hatcher共同撰写。该书旨在帮助读者理解和掌握...
- **数字和日期索引技巧**:介绍如何有效地索引数字和日期数据,以支持高效的查询操作。 - **索引优化**:提供了优化索引性能的方法,包括批量索引、分段合并(Segment Merging)等。 - **近实时搜索**:讨论了如何...
- **数据类型**:支持多种数据类型,如数字类型、字符类型、日期时间类型等。 #### 四、创建和使用存储过程、函数及包 - **存储过程**:用于封装一组SQL语句或PL/SQL代码块,可以在数据库中保存并多次调用。 - **...
- **动态字段类型**:理解Solr如何处理不同类型的字段,包括文本、数字、日期等,以及如何优化字段的存储和搜索性能。 - **自定义分析器**:学习如何创建和应用自定义的分词器和过滤器,以适应特定的语言和内容...
总结下来,这款基于Wepy的记账小程序是一个技术与实用性的结合,它展示了如何利用JavaScript和微信小程序平台实现一个高效、个性化的记账应用。通过学习和分析这个项目,开发者可以掌握Wepy框架的使用、微信小程序的...
总结来说,JSTL是Java Web开发中一个非常实用的工具,通过使用其提供的各种标签,开发者可以更高效地处理常见的页面逻辑,提高代码质量,降低维护成本。对于初学者或有经验的开发者而言,掌握JSTL都是提高开发效率的...