您的位置:首页 > 编程语言 > Java开发

java 和 mysql 获取周 星期 的第一天 最后一天 或者 月的 日期(字符串转日期,日期转字符串,日期加减)

2016-05-05 15:41 831 查看
获取周的第一天,最后一天
System.out.println(getStartEndDate("2016-05-01",1));
获取星期的第一天和最后一天
System.out.println(getStartEndDate("2016-05-01",0));

publicstaticStringgetStartEndDate(StringaDay,inttype){
SimpleDateFormatdf=newSimpleDateFormat("yyyy年M月d日");//("yyyy-MM-ddH:m:s");
Calendarca=Calendar.getInstance();
try{
ca.setTime(newSimpleDateFormat("yyyy-MM-dd").parse(aDay));
}catch(ParseExceptione){
//TODOAuto-generatedcatchblock
e.printStackTrace();
}

Datedate1=null,date2=null;
if(type==0){
intdayOfWeek=ca.get(Calendar.DAY_OF_WEEK);

//中国习惯:周一是一周的开始

if(dayOfWeek==1){

dayOfWeek=7;

}else{

dayOfWeek--;

}

System.out.println(("tag"+"dayofweek="+dayOfWeek+"min="+ca.getActualMinimum(Calendar.DAY_OF_WEEK)+"max="+ca
.getActualMaximum(Calendar.DAY_OF_WEEK)));

Calendarcal=(Calendar)ca.clone();
cal.add(Calendar.DATE,1-dayOfWeek);

date1=cal.getTime();

cal=(Calendar)ca.clone();

cal.add(Calendar.DATE,7-dayOfWeek);

date2=cal.getTime();
}elseif(type==1){

intmaximum=ca.getActualMaximum(Calendar.DAY_OF_MONTH);

intminmum=ca.getActualMinimum(Calendar.DAY_OF_MONTH);

intday=ca.get(Calendar.DAY_OF_MONTH);

Calendarcal=(Calendar)ca.clone();

cal.add(Calendar.DATE,minmum-day);

date1=cal.getTime();

cal=(Calendar)ca.clone();

cal.add(Calendar.DATE,maximum-day);

date2=cal.getTime();

}
Stringstr1=df.format(date1);

Stringstr2=df.format(date2);

System.out.println("tag"+"date1="+str1+"date2="+str2);
returnstr1+"--"+str2;
}



这几天在研究字符串与指定类型的转换,阴差阳错地研究起java的日期应用了,记录下来,希望你有帮助。



根据指定格式的字符串,转换为Date(可研究根据指定格式的字符串,转化为其他指定的类型,如json转换为javaBean)

需要使用到的特殊类:importjava.text.ParsePosition;

/**

*<p>Parsesastringrepresentingadatebytryingavarietyofdifferentparsers.

*

*<p>Theparsewilltryeachparsepatterninturn.

*Aparseisonlydeemedsuccessfulifitparsesthewholeoftheinputstring.

*Ifnoparsepatternsmatch,aParseExceptionisthrown.

*

*@paramstrthedatetoparse,notnull

*@paramparsePatternsthedateformatpatternstouse,seeSimpleDateFormat,notnull

*@paramlenientSpecifywhetherornotdate/timeparsingistobelenient.

*@returntheparseddate

*@throwsIllegalArgumentExceptionifthedatestringorpatternarrayisnull

*@throwsParseExceptionifnoneofthedatepatternsweresuitable

*@seejava.util.Calender#isLenient()

*/

private
static
DateparseDateWithLeniency(

Stringstr,String[]parsePatterns,
boolean
lenient)
throws
ParseException{

if
(str==
null
||parsePatterns==
null
){

throw
new
IllegalArgumentException(
"DateandPatternsmustnotbenull"
);

}


SimpleDateFormatparser=
new
SimpleDateFormat();

parser.setLenient(lenient);

ParsePositionpos=
new
ParsePosition(
0
);

for
(StringparsePattern:parsePatterns){


Stringpattern=parsePattern;


//LANG-530-needtomakesure'ZZ'outputdoesn'tgetpassedtoSimpleDateFormat

if
(parsePattern.endsWith(
"ZZ"
)){

pattern=pattern.substring(
0
,pattern.length()-
1
);

}


parser.applyPattern(pattern);

pos.setIndex(
0
);


Stringstr2=str;

//LANG-530-needtomakesure'ZZ'outputdoesn'thitSimpleDateFormatasitwillParseException

if
(parsePattern.endsWith(
"ZZ"
)){

str2=str.replaceAll(
"([-+][0-9][0-9]):([0-9][0-9])$"
,
"$1$2"
);

}


Datedate=parser.parse(str2,pos);

if
(date!=
null
&&pos.getIndex()==str2.length()){

return
date;

}

}


throw
new
ParseException(
"Unabletoparsethedate:"
+str,-
1
);

}



在java日期格式里,"ZZ"代表的是时区。在java里,格式化需要借助类Formate,同时,parse的时候一般需要借助类parsePosition,
ParsePosition
Format
及其子类所使用的简单类,用来在解析过程中跟踪当前位置。各种
Format
类中的
parseObject
方法要求将
ParsePosition
对象作为一个变量。

日期解释的宽松性:

Calendar
有两种解释日历字段的模式,即lenient和non-lenient。当
Calendar
处于lenient模式时,它可接受比它所生成的日历字段范围更大范围内的值。当
Calendar
重新计算日历字段值,以便由
get()
返回这些值时,所有日历字段都被标准化。例如,lenient模式下的
GregorianCalendar
MONTH==JANUARY
DAY_OF_MONTH==32
解释为February1。

Calendar
处于non-lenient模式时,如果其日历字段中存在任何不一致性,它都会抛出一个异常。例如,
GregorianCalendar
总是在1与月份的长度之间生成
DAY_OF_MONTH
值。如果已经设置了任何超出范围的字段值,那么在计算时间或日历字段值时,处于non-lenient模式下的
GregorianCalendar
会抛出一个异常。(在non-lenient状态下,可以用来检测用户输入的日期是否合法)

日期加减(Calendar的add&&set&&roll)

set(intfield,intamount)方法,并不会立刻就计算出新的日期的值,而是在调用getXxx(),add(),roll()方法才会计算出新的日期的值,即多次调用set方法,也不会产生多余的计算。

add(intfiled,intamount)方法,调用add方法,会立刻计算出新的日期的值。

roll(intfielde,intamount)方法,调用roll方法,也会立刻计算出新的日期的值,与add不同的是,在进行计算完之后,不更改更高字段的值。

举例如下:假设一个日期(Calendar类型)是date20140831
1)调用date.set(Calendar.Month,Calendar.September),在调用set(Calendar.Data,1),c.getTime()返回的时间是20140901
2)调用date.add(Calendar.Month,1),c.getTime()返回的日期是,20141001。(如果是设置了c.setLeniency(true),返回的日期是20141001,如果是设置了c.setLeniency(false),返回的是20140930)
3)调用date.roll(Calendar.Month,13),c.setLeniency(flase),c.getTime()返回的日期是20140930,请注意这里返回的不是20141231

对于设置日期的值,可以这样编写代码:

private
static
Dateset(Datedate,
int
calendarField,
int
amount){

if
(date==
null
){

throw
new
IllegalArgumentException(
"Thedatemustnotbenull"
);

}

//getInstance()returnsanewobject,sothismethodisthreadsafe.

Calendarc=Calendar.getInstance();

c.setLenient(
false
);//这里使用严格模式,要求设置日期的值必须正确

c.setTime(date);

c.set(calendarField,amount);

return
c.getTime();

}


加减日期,可以这样编写代码:

private
static
Dateadd(Datedate,
int
calendarField,
int
amount){

if
(date==
null
){

throw
new
IllegalArgumentException(
"Thedatemustnotbenull"
);

}

Calendarc=Calendar.getInstance();

c.setTime(date);

c.add(calendarField,amount);

return
c.getTime();

}


roll日期,可以这样编写代码:

private
static
Dateroll(Datedate,
int
calendarField,
int
amount){

if
(date==
null
){

throw
new
IllegalArgumentException(
"Thedatemustnotbenull"
);

}

Calendarc=Calendar.getInstance();

c.setTime(date);

c.roll(calendarField,amount);

return
c.getTime();

}



对应的设置年、月、日、时、分、秒,可以这样编写代码:(其他的可以仿写)

public
static
DatesetMinutes(Datedate,
int
amount){

return
set(date,Calendar.MINUTE,amount);

}


借助Calendar提供的api,我们可以获取一些特殊的日期值。如下面这些日期值:

如:get(intfiele)获取给定日历字段的值;getFirstDayOfWeek()获取一星期的第一天的值(1~7)(在不同的地区,每周的第一天会有所不一样,在中是默认一星期的第一天是周日1)。通过这两个函数,我们可以获取任意一天其所在周的第一天的日期值,如20140902周二,我们可以获取到周日的日期值为20140831。具体方法如下:
构造一个20140902的Calendar,通过getFirstDayOfWeek(),获取本周第一天的值(返回1),通过get(Calendar.day_of_week)获取当前日期是本周的第几天,进而获取天数差,再将当前日期减去天数差,即可获取本周第一天的日期值。
函数如下:

public
static
DategetFirstDateOfWeek(Datedate){

Calendarc=Calendar.getInstance();

c.setTime(date);

//获取本周第一天的值

int
firstDayOfWeek=c.getFirstDayOfWeek();

//当前日期是本周的第几天

int
dayOfWeek=c.get(Calendar.DAY_OF_WEEK);


int
day_diff=
1
;
//天数差的绝对值,20140901~20140903天数差为3


if
(firstDayOfWeek<dayOfWeek){

day_diff=Math.abs(dayOfWeek-firstDayOfWeek)+
1
;

}


c.add(Calendar.DATE,
1
-day_diff);


return
c.getTime();

}



为了本地化,我们可以用GregorianCalendar构造Calendar,
GregorianCalendarcalendar=newGregorianCalendar(Local.getDefault());

类似地,我们可以得到本周最后一天的日期:

public
static
DategetLastDateOfWeek(Datedate){

Calendarc=Calendar.getInstance();

c.setTime(date);

//获取本周第一天的值

int
firstDayOfWeek=c.getFirstDayOfWeek();

//当前日期是本周的第几天

int
dayOfWeek=c.get(Calendar.DAY_OF_WEEK);


int
day_diff=
1
;
//天数差的绝对值


if
(firstDayOfWeek<dayOfWeek){

day_diff=Math.abs(dayOfWeek-firstDayOfWeek)+
1
;

}


c.add(Calendar.DATE,
7
-day_diff);


return
c.getTime();

}


再借助
getActualMaximum(intfield)
给定此
Calendar
的时间值,返回指定日历字段可能拥有的最大值。
getActualMinimum(intfield)
给定此
Calendar
的时间值,返回指定日历字段可能拥有的最小值。借助这两个函数,我们可以获取一天所在月的第一天/最后一天的日期。方法如下:

public
static
DategetFirstDateOfMonth(Datedate){

if
(date==
null
){

throw
new
IllegalArgumentException(
"thedatemustnotbenull"
);

}


Calendarc=Calendar.getInstance();

c.setTime(date);

//getthemindateinthismonth

int
min_day=c.getActualMinimum(Calendar.DATE);

c.set(Calendar.DATE,min_day);


return
c.getTime();

}


public
static
DategetLastDateOfMonth(Datedate){

if
(date==
null
){

throw
new
IllegalArgumentException(
"thedatemustnotbenull"
);

}


Calendarc=Calendar.getInstance();

c.setTime(date);

//getthemaxdateinthemonth

int
max_day=c.getActualMaximum(Calendar.DATE);

c.set(Calendar.DATE,max_day);


return
c.getTime();

}


聪明的我们,是否马上就会想到,能否通过getActualMaximum和getActualMininum来获取一周day_of_week的最大/小值呢??是的,通过这两个方法,我们可以减少一定的计算量,如下:

public
static
DategetFirstDateOfWeek(Datedate){

Calendarc=Calendar.getInstance();

c.setTime(date);

////获取本周第一天的值

//intfirstDayOfWeek=c.getFirstDayOfWeek();

////当前日期是本周的第几天

//intdayOfWeek=c.get(Calendar.DAY_OF_WEEK);

//

//intday_diff=1;//天数差的绝对值,20140901~20140903天数差为3

//

//if(firstDayOfWeek<dayOfWeek){

//day_diff=Math.abs(dayOfWeek-firstDayOfWeek)+1;

//}

//

//c.add(Calendar.DATE,1-day_diff);


int
min_day=c.getActualMinimum(Calendar.DAY_OF_WEEK);

c.set(Calendar.DAY_OF_WEEK,min_day);


return
c.getTime();

}


借助getActualMaxinum和getActualMininum可以获得很多最大/小值,如可以获取月、日、时、分、秒的最后/最初一刻,自然就可以获取一年的起始/结束日期,一天的起始/结束时刻等等,发挥想象了,灵活应用api,就可以很多我们所需要的函数,组织起来就可以是一个工具类了。

在这里再谈一下,如果获取季度的起始/结束日期,方法如下:
对于给定的日期,如果我们可以获取到其所在季度的起始月份和结束月份,自然就可以获取到季度的起始日期和结束日期。函数如下:
在这里我们初始化静态数组,用来存储每个月所在季度第一个和最后一个月份的值,注意在java里,月份的范围是[0,11]

private
static
final
int
[]seasonFirstMonth=
new
int
[]{
0
,
0
,
0
,
3
,
3
,
3
,

6
,
6
,
6
,
9
,
9
,
9
};


private
static
final
int
[]seasonLastMonth=
new
int
[]{
2
,
2
,
2
,
5
,
5
,
5
,

8
,
8
,
8
,
11
,
11
,
11
};


public
static
DategetFirstDateOfSeason(Datedate){

if
(date==
null
){

throw
new
IllegalArgumentException(
"thedatemustnotbenull"
);

}


Calendarc=Calendar.getInstance();

c.setTime(date);


c.set(Calendar.MONTH,seasonFirstMonth[c.get(Calendar.MONTH)]);

c.set(Calendar.DATE,c.getActualMinimum(Calendar.DATE));

return
c.getTime();

}


public
static
DategetLastDateOfSeason(Datedate){

if
(date==
null
){

throw
new
IllegalArgumentException(
"thedatemustnotbenull"
);

}


Calendarc=Calendar.getInstance();

c.setTime(date);


c.set(Calendar.MONTH,seasonLastMonth[c.get(Calendar.MONTH)]);

c.set(Calendar.DATE,c.getActualMaximum(Calendar.DATE));

return
c.getTime();

}


最后谈一下,如何去计算两个日期之间的天数差(规定如下,20140901~20140903,天数差为3),函数如下:

public
static
long
getDaysBetweenTwoDate(Datedate1,Datedate2){

if
(date1==
null
||date2==
null
){

throw
new
IllegalArgumentException(
"date1anddate2mustnotbenull"
);

}


Calendarc1=Calendar.getInstance();

c1.setTime(date1);


Calendarc2=Calendar.getInstance();

c2.setTime(date2);


long
mills_one_day=
60
*
60
*
24
*
1000
;


return
Math.abs(c1.getTimeInMillis()-c2.getTimeInMillis())/mills_one_day+
1
;

}


附:通过阅读JavaAPI,借助一些基础的推算逻辑,我们可以合成很多很有用工具类,让我们彼此一起努力。在这一次学习当中,本人更感兴趣的,如何通过指定的字符串格式构造指定的对象(如通过字符串构造日期),又如何通过指定格式输出制定对象(如根据yyyyMMdd格式输出日期对象)。


MYSQL中的获取:

#当年第一天:
SELECTDATE_SUB(CURDATE(),INTERVALdayofyear(now())-1DAY);

#当年最后一天:
SELECTconcat(YEAR(now()),'-12-31');

#当前week的第一天:
selectdate_sub(curdate(),INTERVALWEEKDAY(curdate())+1DAY);

#当前week的最后一天:
selectdate_sub(curdate(),INTERVALWEEKDAY(curdate())-5DAY);

#前一week的第一天:
selectdate_sub(curdate(),INTERVALWEEKDAY(curdate())+8DAY);

#前一week的最后一天:
selectdate_sub(curdate(),INTERVALWEEKDAY(curdate())+1DAY);

#前两week的第一天:
selectdate_sub(curdate(),INTERVALWEEKDAY(curdate())+15DAY);

#前两week的最后一天:
selectdate_sub(curdate(),INTERVALWEEKDAY(curdate())+9DAY);

#当前month的第一天:
SELECTconcat(date_format(LAST_DAY(now()),'%Y-%m-'),'01');

#当前month的最后一天:
SELECTLAST_DAY(now());

#前一month的第一天:
SELECTconcat(date_format(LAST_DAY(now()-interval1month),'%Y-%m-'),'01');

#前一month的最后一天:
SELECTLAST_DAY(now()-interval1month);

#前两month的第一天:
SELECTconcat(date_format(LAST_DAY(now()-interval2month),'%Y-%m-'),'01');

#前两month的最后一天:
SELECTLAST_DAY(now()-interval2month);

#当前quarter的第一天:
selectconcat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEARFROMCURDATE()),1)+intervalQUARTER(CURDATE())*3-3month),'%Y-%m-'),'01');

#当前quarter的最后一天:
selectLAST_DAY(MAKEDATE(EXTRACT(YEARFROMCURDATE()),1)+intervalQUARTER(CURDATE())*3-1month);

#前一quarter的第一天:
selectconcat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEARFROMCURDATE()),1)+intervalQUARTER(CURDATE())*3-6month),'%Y-%m-'),'01');

#前一quarter的最后一天:
selectLAST_DAY(MAKEDATE(EXTRACT(YEARFROMCURDATE()),1)+intervalQUARTER(CURDATE())*3-4month);

#前两quarter的第一天:
selectconcat(date_format(LAST_DAY(MAKEDATE(EXTRACT(YEARFROMCURDATE()),1)+intervalQUARTER(CURDATE())*3-9month),'%Y-%m-'),'01');

#前两quarter的最后一天:
selectLAST_DAY(MAKEDATE(EXTRACT(YEARFROMCURDATE()),1)+intervalQUARTER(CURDATE())*3-7month);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
章节导航