一个日历输入空间的程序,我改的,加上了小时、分钟的输入。

该博客主要展示了JavaScript实现日历功能的代码。包含获取当前日期、上周日期的函数,还有构建日历、绘制日历、更新日历等功能函数。此外,还给出了测试页面test.htm和处理页面testc.jsp的代码,用于验证日历功能。

calendar.js

function getNowDate()
{
   var nn=new Date();
   year1=nn.getYear();
   mon1=nn.getMonth()+1;
   date1=nn.getDate();
   var monstr1;
   var datestr1
   if(mon1<10)
    monstr1="0"+mon1;
   else
    monstr1=""+mon1;
    
   if(date1<10)
     datestr1="0"+date1;
   else
     datestr1=""+date1;
   return year1+"-"+monstr1+"-"+datestr1;
}
function getlastweekDate()
{
   var nn=new Date();
   year1=nn.getYear();
   mon1=nn.getMonth()+1;
   date1=nn.getDate();
  
   var mm=new Date(year1,mon1-1,date1);
   var tmp1=new Date(2000,1,1);
   var tmp2=new Date(2000,1,15);
   var ne=tmp2-tmp1;
   var mm2=new Date();
   mm2.setTime(mm.getTime()-ne);
  
  
   year2=mm2.getYear();
   mon2=mm2.getMonth()+1;
   date2=mm2.getDate();
   
   
     if(mon2<10)
    monstr2="0"+mon2;
   else
    monstr2=""+mon2;
    
   if(date2<10)
     datestr2="0"+date2;
   else
     datestr2=""+date2;
 
  
    return year2+"-"+monstr2+"-"+datestr2;
}

var gdCtrl = new Object();
var goSelectTag = new Array();
var gcGray   = "#808080";
//var gcToggle = "#FB8664";
var gcToggle = "#7777ff";
//var gcBG = "#e5e6ec";
var gcBG = "#ffffff";
var previousObject = null;

var gdCurDate = new Date();
var giYear = gdCurDate.getFullYear();
var giMonth = gdCurDate.getMonth()+1;
var giDay = gdCurDate.getDate();
var giHour="00";
var giMinute="00";


function fSetDate(iYear, iMonth, iDay,iHour,iMinute){
  VicPopCal.style.visibility = "hidden";
  if ((iYear == 0) && (iMonth == 0) && (iDay == 0)){
   gdCtrl.value = "";
  }else{
   iMonth = iMonth + 100 + "";
   iMonth = iMonth.substring(1);
   iDay   = iDay + 100 + "";
   iDay   = iDay.substring(1);
   iHour   = iHour + 100 + "";
   iHour   = iHour.substring(1);
   iMinute   =  iMinute + 100 + "";
   iMinute   =  iMinute.substring(1);

   if(gdCtrl.tagName == "INPUT"){
      gdCtrl.value = iYear+"-"+iMonth+"-"+iDay+" "+iHour+":"+iMinute;
   }else{
      gdCtrl.innerText = iYear+"-"+iMonth+"-"+iDay+" "+iHour+":"+iMinute;
   }
  }
 
  for (i in goSelectTag)
   goSelectTag[i].style.visibility = "visible";
  goSelectTag.length = 0;
 
  window.returnValue=gdCtrl.value;
  //window.close();
  //qhk add
  if (yearNameObject!=null && monthNameObject!=null && dateNameObject!=null)
  {
   if (gdCtrl.value=="")
   {
    yearNameObject.value="";
    monthNameObject.value="";
    dateNameObject.value="";
   }
   else
   {
    yearNameObject.value=gdCtrl.value.substring(0,4);
    monthNameObject.value=gdCtrl.value.substring(5,7);
    dateNameObject.value=gdCtrl.value.substring(8,10);
   }
   yearNameObject=null;
   monthNameObject=null;
   dateNameObject=null;
  }
}

function HiddenDiv()
{
 var i;
  VicPopCal.style.visibility = "hidden";
 // Masked by Guozhong Zhang/Precom
  for (i in goSelectTag)
   goSelectTag[i].style.visibility = "visible";
  goSelectTag.length = 0;

}
function fSetSelected(aCell){
  var iOffset = 0;
  var iYear = parseInt(tbSelYear.value);
  var iMonth = parseInt(tbSelMonth.value);
  var iHour = parseInt(tbSelHour.value);
  var iMinute = parseInt(tbSelMinute.value);
 
  aCell.bgColor = gcBG;
  with (aCell.children["cellText"]){
   var iDay = parseInt(innerText);
   if (color==gcGray)
  iOffset = (Victor<10)?-1:1;
 iMonth += iOffset;
 if (iMonth<1) {
  iYear--;
  iMonth = 12;
 }else if (iMonth>12){
  iYear++;
  iMonth = 1;
 }
  }
  fSetDate(iYear, iMonth, iDay,iHour,iMinute);
}

function Point(iX, iY){
 this.x = iX;
 this.y = iY;
}

function fBuildCal(iYear, iMonth) {
  var aMonth=new Array();
  for(i=1;i<7;i++)
   aMonth[i]=new Array(i);
 
  var dCalDate=new Date(iYear, iMonth-1, 1);
  var iDayOfFirst=dCalDate.getDay();
  var iDaysInMonth=new Date(iYear, iMonth, 0).getDate();
  var iOffsetLast=new Date(iYear, iMonth-1, 0).getDate()-iDayOfFirst+1;
  var iDate = 1;
  var iNext = 1;

  for (d = 0; d < 7; d++)
 aMonth[1][d] = (d<iDayOfFirst)?-(iOffsetLast+d):iDate++;
  for (w = 2; w < 7; w++)
   for (d = 0; d < 7; d++)
  aMonth[w][d] = (iDate<=iDaysInMonth)?iDate++:-(iNext++);
  return aMonth;
}

function fDrawCal(iYear, iMonth, iCellHeight, sDateTextSize) {
  var WeekDay = new Array("日","一","二","三","四","五","六");
  var styleTD = " bgcolor='"+gcBG+"' bordercolor='"+gcBG+"' valign='middle' align='center' height='"+iCellHeight+"' style='font:arial "+sDateTextSize+";";            //Coded by Liming Weng(Victor Won) email:victorwon@sina.com

  with (document) {
   for (w = 1; w < 7; w++) {
  write("<tr>");
  for (d = 0; d < 7; d++) {
   write("<td id=calCell "+styleTD+"cursor:hand;' onMouseOver='this.bgColor=gcToggle' onMouseOut='this.bgColor=gcBG' onclick='fSetSelected(this)'>");
   write("<font id=cellText Victor='Liming Weng' size=2> </font>");   
   write("</td>");
   write("<TD>");


  }
  write("</tr>");
 }
  }
}

function fUpdateCal(iYear, iMonth) {
  myMonth = fBuildCal(iYear, iMonth);
  var i = 0;
  for (w = 0; w < 6; w++)
 for (d = 0; d < 7; d++)
  with (cellText[(7*w)+d]) {
   Victor = i++;
   if (myMonth[w+1][d]<0) {
    color = gcGray;
    innerText = -myMonth[w+1][d];
   }else{
    color = ((d==0)||(d==6))?"red":"black";
    innerText = myMonth[w+1][d];
   }
  }
}

function fSetYearMon(iYear, iMon){
  tbSelMonth.options[iMon-1].selected = true;
  for (i = 0; i < tbSelYear.length; i++)
 if (tbSelYear.options[i].value == iYear)
  tbSelYear.options[i].selected = true;
  fUpdateCal(iYear, iMon);
}

function fPrevMonth(){
  var iMon = tbSelMonth.value;
  var iYear = tbSelYear.value;
 
  if (--iMon<1) {
   iMon = 12;
   iYear--;
  }
 
  fSetYearMon(iYear, iMon);
}

function fNextMonth(){
  var iMon = tbSelMonth.value;
  var iYear = tbSelYear.value;
 
  if (++iMon>12) {
   iMon = 1;
   iYear++;
  }
 
  fSetYearMon(iYear, iMon);
}

function fToggleTags(){
  with (document.all.tags("SELECT")){
  for (i=0; i<length; i++)
   if ((item(i).Victor!="Won")&&fTagInBound(item(i))){
    item(i).style.visibility = "hidden";
    goSelectTag[goSelectTag.length] = item(i);
   }
  }
}

function fTagInBound(aTag){
  with (VicPopCal.style){
   var l = parseInt(left);
   var t = parseInt(top);
   var r = l+parseInt(width);
   var b = t+parseInt(height);
 var ptLT = fGetXY(aTag);
 return !((ptLT.x>r)||(ptLT.x+aTag.offsetWidth<l)||(ptLT.y>b)||(ptLT.y+aTag.offsetHeight<t));
  }
}

function fGetXY(aTag){
  var oTmp = aTag;
  var pt = new Point(0,0);
  do {
   pt.x += oTmp.offsetLeft;
   pt.y += oTmp.offsetTop;
   oTmp = oTmp.offsetParent;
  } while(oTmp.tagName!="BODY");
  return pt;
}

// Main: popCtrl is the widget beyond which you want this calendar to appear;
//       dateCtrl is the widget into which you want to put the selected date.
// i.e.: <input type="text" name="dc" style="text-align:center" readonly><INPUT type="button" value="V" onclick="fPopCalendar(dc,dc);return false">
function fPopCalendar(popCtrl, dateCtrl,strDate){
  if (popCtrl == previousObject){
    if (VicPopCal.style.visibility == "visible"){
    HiddenDiv();
    return true;
   }
   
  }
  previousObject = popCtrl;
  gdCtrl = dateCtrl;
  fInitialDate(strDate);
  fSetYearMon(giYear, giMonth);
  var point = fGetXY(popCtrl);
  with (VicPopCal.style) {
   left = point.x;
 top  = point.y+popCtrl.offsetHeight;
 width = VicPopCal.offsetWidth;
 // Added by Danian Zhang/SUI
 //width = 210;
 // Modified by Guozhong Zhang/Precom
 width = 295;
 height = VicPopCal.offsetHeight;
 //Cover the Object under it
 fToggleTags(point);  
 visibility = 'visible';
  }
}
//已经使用三个input(或select)项作为日期输入的程序,不想进行action修改,可调用以下函数,将日期作为隐藏域
var yearNameObject;
var monthNameObject;
var dateNameObject;
function newfPopCalendar(popCtrl,dateCtrl,yearName,monthName,dateName,strDate)
{
 fPopCalendar(popCtrl,dateCtrl,strDate);
 if (document.all.item(yearName).length==null)
 {
  yearNameObject=document.all.item(yearName);
  monthNameObject=document.all.item(monthName);
  dateNameObject=document.all.item(dateName);
 }
 else
 {
  yearNameObject=document.all.item(yearName)[document.all.item(yearName).length-1];
  monthNameObject=document.all.item(monthName)[document.all.item(monthName).length-1];
  dateNameObject=document.all.item(dateName)[document.all.item(dateName).length-1];
 }
}
//qhk --end
// Added by Danian Zhang/SUI
function fInitialDate(strDate){
 if( strDate == null || strDate.length != 10 )
  return false;

 var sYear  = strDate.substring(0,4);
 var sMonth = strDate.substring(5,7);
 var sDay   = strDate.substring(8,10);

 if( sMonth.charAt(0) == '0' ) { sMonth = sMonth.substring(1,2); }
 if( sDay.charAt(0)   == '0' ) { sDay   = sDay.substring(1,2);   }

 var nYear  = parseInt(sYear );
 var nMonth = parseInt(sMonth);
 var nDay   = parseInt(sDay  );
 
 if ( isNaN(nYear ) ) return false;
 if ( isNaN(nMonth) ) return false;
 if ( isNaN(nDay  ) ) return false;

 var arrMon = new Array(12);
 arrMon[ 0] = 31; arrMon[ 1] = nYear % 4 == 0 ? 29:28;
 arrMon[ 2] = 31; arrMon[ 3] = 30;
 arrMon[ 4] = 31; arrMon[ 5] = 30;
 arrMon[ 6] = 31; arrMon[ 7] = 31;
 arrMon[ 8] = 30; arrMon[ 9] = 31;
 arrMon[10] = 30; arrMon[11] = 31;

 if ( nYear  < 1900 || nYear > 2100 )   return false;
 if ( nMonth < 1 || nMonth > 12 )    return false;
 if ( nDay < 1 || nDay > arrMon[nMonth - 1] ) return false;

 giYear  = nYear;
 giMonth = nMonth;
 giDay   = nDay;
 return true;
}

var gMonths = new Array("一月","二月","三月","四月","五月","六月","七月","八月","九月","十月","十一月","十二月");

with (document) {
// Modified by Guozhong Zhang/Precom
//write("<Div id='VicPopCal' style='OVERFLOW:hidden;POSITION:absolute;VISIBILITY:hidden;border:2px ridge;z-index:100;'>");
write("<Div id='VicPopCal' style='OVERFLOW:hidden;POSITION:absolute;VISIBILITY:hidden;border:2px ridge;z-index:100;'>");
write("<table border='0' bgcolor='#cccccc'>");
write("<TR>");
write("<td valign='middle' align='center'><input type='button' name='PrevMonth' value='<' style='height:20;width:20;FONT:bold' onClick='fPrevMonth()'>");
write("<SELECT name='tbSelYear' onChange='fUpdateCal(tbSelYear.value, tbSelMonth.value)' Victor='Won'>");
 // Modified by Guozhong Zhang/Precom
    //for(i=1900;i<2015;i++)
for(i=2000;i<2015;i++)
 write("<OPTION value='"+i+"'>"+i+" 年</OPTION>");
write("</SELECT>");
write("<select name='tbSelMonth' onChange='fUpdateCal(tbSelYear.value, tbSelMonth.value)' Victor='Won'>");
for (i=0; i<12; i++)
 write("<option value='"+(i+1)+"'>"+gMonths[i]+"</option>");
write("</SELECT>");
write("<input type='button' name='PrevMonth' value='>' style='height:20;width:20;FONT:bold' onclick='fNextMonth()'>");
write("</td>");
write("</TR><TR>");

write("<TD align='center'>");
write("<TABLE width='100%'><TR>");
  var WeekDay2 = new Array("日","一","二","三","四","五","六");
 for(i=0; i<7; i++){
  write("<td color:#000000' style='font:bold arial'>");
 // Added by Guozhong Zhang/Precom
 write("<font size=2>");   
  write( WeekDay2[i]);
 // Added by Guozhong Zhang/Precom
 write("</font>");   
  write("</td>");
 }
write("</tr></table>");
write("</TD></TR>");


write("<td align='center'>");
 // Modified by Guozhong Zhang/Precom
    //write("<DIV style='background-color:teal'><table width='100%' border='0'>");
write("<DIV style='background-color:white'><table width='100%' border='0'>");
fDrawCal(giYear, giMonth, 18, '12');
write("</table></DIV>");
write("</td>");
write("</TR><TR><TD align='center'>");
write("<TABLE width='100%'><TR><TD align='center'>");
write("<B style='cursor:hand' onclick='fSetDate(0,0,0,0,0)' onMouseOver='this.style.color=gcToggle' onMouseOut='this.style.color=0'><font size=2>清空</font></B>");
write("</td><td align='center'>");
write("<B style='cursor:hand' onclick='fSetDate(giYear,giMonth,giDay,0,0)' onMouseOver='this.style.color=gcToggle' onMouseOut='this.style.color=0'><font size=2>今天: "+giYear+"-"+giMonth+"-"+giDay+"</font></B>");
write("</td></tr></table>");
write("</TD>");


write("<TD style='color:gcToggle' width='80px'><span style='top:50;position:absolute;font-size:12px' width='80px'>");
var gHour = new Array("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23");
write("&nbsp;<select name='tbSelHour' onChange='fUpdateCal(tbSelYear.value, tbSelMonth.value)'  Victor='Won'>");
for (i=0; i<24; i++)
 write("<option value='"+gHour[i]+"'>"+gHour[i]+"</option>");
write("</select>小时<br><br><br>");

var gMinute = new Array("00","01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16","17","18","19","20","21","22","23","24","25","26","27","28","29","30","31","32","33","34","35","36","37","38","39","40","41","42","44","45","46","47","48","49","50","51","52","54","55","56","57","58","59");
write("&nbsp;<select name='tbSelMinute' onChange='fUpdateCal(tbSelYear.value, tbSelMonth.value)'  Victor='Won' style='width:40px'>");
for (i=0; i<59; i++)
 write("<option value='"+gMinute[i]+"'>"+gMinute[i]+"</option>");
write("</select>分钟");

write("</span></TD>");
write("</TR>");

write("</TABLE></Div>");
}

test.htm

<html>
<head>
<title>test</title>
<script language="javascript" src="calendar.js"></script>
</head>
<body>
<form action="testc.jsp" name="form1">
<p>新闻日期:
  <input type="text" name="news_date" readonly size="20" onClick="fPopCalendar(news_date,news_date);return false">
<input type="submit" value="tijiao">
</form>
</body>

    
</html>

testc.jsp

<%@ page language="java" %>
<%@ page import="java.util.*" %>
<%
String datetime=request.getParameter("news_date");
out.println(datetime);
%>

<think>我们被要求:获取当前时间五个工作日后的时间,并以字符串格式(年月日时分秒)输出的Java实现。注意是五个工作日,即需要跳过周末(周六和周日)。思路:1.获取当前时间(LocalDateTime或LocalDate,但考虑到我们最终要精确到时分秒,使用LocalDateTime)。2.然后我们需要添加5个工作日(跳过周六、周日)。注意:我们可能需要考虑节假日,但是题目中没有提到节假日,所以默认只跳过周末。3.因为每个工作日是周一到周五,所以我们需要循环5次,每次加一天,如果遇到周六或周日,则跳过(即额外多加一天,直到遇到下一个工作日)。4.但是注意,如果当前是周五,那么下一个工作日是下周一,即加3天。但更通用的做法是:从当前日期开始,每次加一天,判断是否是工作日(周一到周五),如果不是则继续加,直到我们添加了5个有效的工作日。5.在跳过周末的情况下,添加5个工作日,实际可能需要5天到7天(例如,如果当前是周五,那么加5个工作日需要跳过两天周末,实际需要5+2=7天?不对,应该是:从周五开始,下一个工作日是下周一,所以加一天(变成周六)不是工作日,再加一天(周日)也不是,再加一天(周一)才是一个工作日。所以5个工作日应该是:第1个工作日:周五->下周一(加3天)得1个工作日然后继续加1天(周二)得第二个工作日,加1天(周三)第三个,加1天(周四)第四个,加1天(周五)第五个。所以总共加了3(跳到周一)+4(从周一到周五)=7天?不对,实际上从周五开始,加5个工作日应该是下一个周一、二、三、四、五,所以需要加上3天(从周五到周一)然后再加上4天(即总共加7天)得到下周五?其实我们只需要循环5次,每次遇到工作日才计数。6.具体步骤:-从当前日期时间开始(假设为start)-设置一个计数器,初始为0-循环,每次加1天,然后判断这一天是不是工作日(即星期一到星期五)-如果是,则计数器加1-直到计数器达到57.注意:这里我们可能不需要考虑时间部分,因为我们只需要添加天数,但是题目要求输出到时分秒。那么我们可以在开始时获取当前时间的时分秒,然后在计算完日期后再合并时间?但是如果我们使用LocalDateTime,就可以直接处理。8.另外,假设当前时间是在工作日(比如周一到周五),但我们不能保证当前时间在周末调用(虽然题目说当前时间,但我们的程序应具有通用性)。所以开始时间可能是周末,那么我们需要先跳到下一个工作日吗?注意:题目要求“五个工作日后的时间”,当前时间可能是周末,那么当前时间本身不算工作日。所以我们需要从当前时间开始,先找到下一个工作日(即如果当前是周六或周日,先跳到下周一),然后再开始计数5个工作日。但是题目没有明确要求当前时间如果是非工作日如何计算,通常业务逻辑是:如果当前是工作日,那么从当前开始算第一天(但当天算不算一个工作日?)。常见做法是:-如果要求“5个工作日之后”,通常不包括当前日,即从下一个工作日开始计数。但有时也可能包括当前日(如果当前是工作日)。所以我们需要明确:*情况1:当前是工作日,那么5个工作日就是当前日期加上5个工作日(跳过周末)。*情况2:当前是非工作日(周末),那么5个工作日就是从下一个周一开始,计数5个工作日。然而,更常见的需求是:不管当前是不是工作日,我们都从下一个工作日开始计数5个工作日?或者从当前日期开始,包括当前日(如果当前日是工作日)?题目没有明确,但通常我们会理解为:-如果今天是周一,那么5个工作日就是下周一(即5天后,跳过周末)?但是注意,5个工作日应该是:周一(当天)算第1天,周二第2天,周三第3天,周四第4天,周五第5天。所以结果应该是本周五。-另一种理解:5个工作日之后,即加上5个工作日,那么今天不算,从明天开始算第一个工作日。但题目要求“当前时间加五个工作日”,并没有明确是否包含当天。在实际业务中,当天如果是工作日,往往也是被计算在内的(例如,T+5个工作日)。因此,我们采用如下策略:-如果当前时间是工作日(星期一到星期五),那么从当前时间开始,然后我们加上5个工作日(包括当天,所以实际上只需要再加4个工作日)?不对,加上5个工作日,应该包括当天吗?-例如,今天是周一,加上5个工作日,应该是周五(因为周一到周五是5天)。所以:工作日1:周一(当天)工作日2:周二工作日3:周三工作日4:周四工作日5:周五(结果)因此,我们只需要添加4天(因为周一已经是第一个工作日)?不对,因为周一当天已经算一个工作日了,我们要加5个工作日,那么到周五是5个工作日(包括周一)。所以结果日期应该是同周的周五。-另一种做法:不管当天是不是工作日,我们都要加上5个工作日(即5个有效的工作日),那么:如果当前是工作日,则从当前开始,我们需要累计5个工作日(包括当前日?不包括?因为“加”5个工作日,通常不包括当前日)。比如,从当前日(周一)开始,加上5个工作日,应该是从当前日之后加5个工作日(即下周一)。但是这样理解与我们的直觉不符(因为周一到周五就是5个工作日)。我们重新理解题目:要求“当前时间加五个工作日”,即当前时间(某一时刻)加上5个工作日,工作日就是周一到周五。所以:-如果我们把工作日当作时间单位(就像5天一样),但是工作日单位会跳过周末。所以我们需要加上5个工作日(即5个有效的工作日,周末不算)。但注意:当前时间如果是周五下午,那么加上5个工作日,应该是下周五下午。而不会把周末算进去。因此,我们不应该将当前日计入计数(因为加上5个工作日就是再往后推5个工作日,不包括当前日?),还是包括?这里存在歧义。为了明确,我们参考常见的“工作日”计算:通常是T+N个工作日,T是当前日期(如果当前是工作日,则T是当前;如果是非工作日,则T是下一个工作日),然后计算N个工作日后的日期。所以,做法:-如果当前是工作日,那么从当前开始,我们要加5个工作日(不包括当前日,即接下来的5个工作日)。-或者,包括当前日?如果我们从当前日开始算,那么当前日算第0天,然后加5个工作日?这也不对。标准金融计算中,T+5个工作日:交易日T(如果是工作日)算作T,然后接下来的5个交易日。例如,T是周一,那么T+5就是下周一(因为周二、周三、周四、周五、下周一,共5个交易日)?但实际上,周一到周五有5天,所以T+5应该是周五。但是,我们通常说的“5个工作日之后”指包含5个完整的交易日(不含T日)。这种说法也有。由于题目没有明确,我们采用最常见的理解:工作日不包括周末,所以我们需要跳过周末。我们定义:-给定一个开始日期,我们添加5个有效工作日(即跳过周末),并且开始日期如果是非工作日(周末),则先调整到下一个工作日(周一)作为开始,然后再加5个工作日(即5天,但跳过周末)。然而,题目是“加五个工作日”,所以我们不妨这样:-先调整当前日期到最近的工作日(如果当前是周末,则调整到下一个周一),然后在此基础上加上5个工作日(也就是4天?不对,因为5个工作日需要5天,但是跳过周末)。所以我们需要循环5次,每次加1个工作日。但是,这里有一个更简单的算法:先加上5天(自然日),然后再加上中间包含的周末天数?这样比较复杂,因为跨周末的情况需要判断。因此,我们采用循环方式,每次增加一天,判断是否为工作日(周一到周五),如果是则计数器加1,直到计数器达到5。注意,我们可能还需要考虑当前时间是不是非工作日,需要调整到下一个工作日吗?重新分析:题目要求“当前时间加五个工作日”,那么如果当前是周末,应该先调整到下一个工作日(周一)作为起点吗?但是这样就会多调整一次。我们也可以把调整工作日和计算5个工作日合并到循环里。具体步骤:step1:获取当前日期时间(LocalDateTimenow=LocalDateTime.now())step2:设置计数器count=0,然后从当前时间开始,不断增加1天(使用plusDays(1)),直到我们添加了5个工作日(计数器达到5)。但是,注意:我们不应该变当前时间的小时分钟秒?因为加天数并不会变时间部分(比如下午两点加一天还是下午两点)。但是,这里有一个重要问题:当前时间如果是非工作日,我们是否立刻跳到下一个工作日?还是说当前时间也算一天?根据“加五个工作日”,我们的起点应该是当前时间,但是我们需要跳过非工作日。所以:情况1:如果当前时间是工作日,那么我们需要在之后的时间中寻找5个工作日(不包括当前,所以我们要找的是当前时间之后的5个工作日?)。不对,应该是当前时间加上5个工作日,即5个工作日之后的时间。那么第一个工作日应该是当前时间加1个工作日?如果我们包含当前日,那么当前日就是第一个工作日。但题目说“加五个工作日”,通常不包括当前日。为了统一,我们这样处理:-定义目标日期=当前日期时间-我们需要加上5个工作日(5个工作日的长度)。因此,我们循环5次,每次将目标日期往后推一天,然后判断推后的这一天是否为工作日(周一到周五),如果是,就算一次有效的工作日增加;如果不是,就继续推后一天(不计入计数),直到我们增加了5个有效的工作日。注意,这里我们每次推后一天,然后判断这一天是不是工作日,如果是则计数一次。这样,我们跳过了周末,并且不会变时间部分(因为plusDays(1)保持时间不变)。但是,这个循环开始前,我们并没有处理当前日期是不是非工作日?实际上,我们并不需要特别处理。因为我们的做法是:从当前时间开始,先加上1天,然后判断这天是不是工作日,如果是,则计入一次,这样连续5次有效的工作日。为什么从加上1天开始?因为“加五个工作日”通常不包括当天。例如,今天(周一)加5个工作日,我们想要的是周五(即4天后)。所以我们要加5个工作日,我们加5次(每次1个工作日):第1次:周二(工作日)->计数1第2次:周三(工作日)->计数2第3次:周四(工作日)->计数3第4次:周五(工作日)->计数4第5次:下周一(工作日)->计数5那么最终结果是下周一?但是我们期望的是周五。问题就出在:我们开始计数前,没有包含当前日(周一)。所以,如果我们想要包含当前日,那么我们就不能从当前日加一天开始。因此,我们需要考虑是否包含当前日。由于题目没有明确,我们采用金融领域常见的T+5:T是交易日(如果当前是交易日,则T是当前),然后T+5就是从T开始往后数5个交易日(包括T)。那么:周一(T)+0=周一(T)周一(T)+1=周二(T+1)...周一(T)+4=周五(T+4)->这里就是5个交易日(周一到周五共5天)所以,实际上我们只需要加上4天(自然日)就可以得到周五(因为没有周末跳过)。但是,如果T是周五,那么:T(周五)+1=下周一(跳过周末)->相当于加1个交易日T(周五)+2=下周二...直到T+4(跳过两个周末?这里不对,因为周五之后的下一个交易日是周一,所以周五加1个交易日就是周一,加2个交易日是周二,加3个是周三,加4个是周四,加5个是周五(下周五)?)而实际上,周五加上5个交易日应该是下周五(5个交易日:下周一、二、三、四、五)。所以我们需要加上5个交易日,但是自然日需要7天(周五加7天是下周五)。因此,我们采用的算法是:1.获取当前时间(称为current)2.设置一个目标时间(初始为current)3.设置需要添加的工作日数n=54.循环n次,每次:a.将目标时间加上一天(此时是自然日加一天)b.然后检查这个目标时间是不是周六或周日,如果是,则继续加一天,直到是工作日(周一到周五)为止。c.这样,循环5次后,目标时间就是5个工作日后的时间。注意:这个方法,对于当前时间如果是周末,会怎样?假设当前是周六:第1次循环:目标时间先加1天(变成周日)->是周末,则继续加(变成周一,工作日)->第一个工作日完成(但实际上周六开始,我们加了一天变成周日,再加一天变成周一,所以第一个工作日是周一)。然后还需要4次:分别加上周二、周三、周四、周五(都是工作日),所以最后得到的是周五。但是,这里我们并没有将周六调整到周一作为起点,而是通过循环自动跳过了。所以,这样我们实现了从当前时间(周六)加上5个工作日(实际自然日加了6天)得到下周五。这个算法有一个问题:循环5次,每次加1天并跳过周末,这样我们得到的时间是5个工作日之后,但是它可能并不包括当前日(如果当前是工作日)。例如,当前是周五:第一次循环:当前是周五,加一天变成周六(跳过),再加一天变成周日(跳过),再加一天变成周一(工作日),这时第一个工作日完成(周一)。然后循环4次,得到周五(即下周五)。所以最后结果是下周五。但是,按照包含当前日(周五)为第一个工作日的话,我们应该只需要再加4个工作日(下一个周一、二、三、四)就可以得到第四个工作日(周四)?不对,因为周五加上5个工作日(包括周五当天)应该是:周五(1)、下周一(2)、下周二(3)、下周三(4)、下周四(5)?不对,周五之后的5个工作日应该是下周二、三、四、五、再下周一?这样显然不对。重新考虑:我们究竟要不要包含当前日?题目要求是“加五个工作日”,这个“加”意味着在原来的基础上添加5个单位,所以不应该包含当前日。因此,无论当前是周几,我们都是往后推5个工作日。所以,我们算法是:跳过当前日,从下一个自然日开始判断,连续跳过周末直到5个工作日。因此,正确的循环应该是:target=current//当前时间n=5while(n>0):target=target.plusDays(1)//加一天if(target是工作日){n--;//如果加一天后是工作日,则计数减一}循环结束后,target就是结果。这个算法保证了:-如果当前是工作日,那么我们不会立即使用当前日(而是从下一天开始计算),所以周五加上5个工作日:从周六开始,然后加到周日(都不算),然后周一(计数1),周二(2),周三(3),周四(4),周五(5)->结果是下周五(因为当前是周五,那么下一个工作日是下周一,然后数5个工作日到下周五)-但是,我们希望周五加上5个工作日的结果应该是下周五(中间跳过了一个周末,然后又加了5个工作日,所以自然日增加了7天)。这符合预期。但是,这样计算,从当前日到结果日期,实际的自然日天数可能超过5天(遇到周末会延迟)。符合跳过周末的要求。但是,注意:时间部分我们只增加天数,时间保持不变。例如,当前是周五下午3点,那么下周五也是下午3点。因此,代码步骤:-获取当前日期时间(LocalDateTime)-设置一个目标时间(初始值为当前时间)-循环5次(每次表示一个工作日,但是需要跳过周末):将目标时间加1天然后检查加1天后的日期是星期几:-如果是周六或周日,则继续加1天(直到变为工作日),但是注意:继续加1天可能还会遇到周末,所以应该用while循环,直到遇到工作日。注意:当我们使用while循环跳过周末时,我们只需要确保加1天后是工作日,然后再进入下一次循环(直到5次都完成)。-循环5次后,目标时间就是5个工作日后的时间。-然后使用DateTimeFormatter将目标时间格式化为"yyyyMMddHHmmss"。但是,这里有一个小问题:我们在循环中每加一天,如果是非工作日,则继续加,直到是工作日,然后计数减1。所以我们需要一个内层的循环来跳过连续的周末。伪代码:intworkingDays=5;LocalDateTimeresult=currentDateTime;while(workingDays>0){result=result.plusDays(1);//先加一天//检查是否是周末DayOfWeekdow=result.getDayOfWeek();if(dow!=DayOfWeek.SATURDAY&&dow!=DayOfWeek.SUNDAY){//是工作日,则计数器减1workingDays--;}}这个循环可以保证我们增加了5个工作日(跳过所有周末)。注意,我们是从当前日期的下一天开始计数的,所以不包含当天。例如,今天是周一,我们加5个工作日:第1次:result加1天变为周二->周二不是周末,所以计数减1(剩余4),然后继续:第2次:加1天(周三)->减1(剩3)第3次:周四(剩2)第4次:周五(剩1)第5次:加一天变成周六(周末,不计)->循环再加一天变成周日(周末,不计)->再加一天变成下周一(工作日),然后减1(剩0),循环结束。那么结果是下周一?但我们期望的是5个工作日后的时间应该是周五(因为周一到周五只有5天)?不对,因为我们每次从当前日期开始加1天(从周一加1天变成周二)就计数减1,那么循环5次就变成加5个工作日(跳过周末),即加了5个有效的工作日,最后的时间是下周一(对于周一来说,这个算法结果是下周一?不是周五)。问题出在:我们当前是周一,我们希望5个工作日后的时间是周五(因为5个工作日就是5天,都在同一周)。但是按照上面的算法:current是周一第一次循环(加1天):周二->工作日,workingDays=4第二次循环(加1天):周三->工作日,workingDays=3第三次循环:周四->2第四次循环:周五->1第五次循环:加1天变成周六(周末)->跳过,继续加,周日(跳过),周一(变成下周一)->工作日,workingDays=0,结束。结果就是下周一。显然,这不符合预期(我们希望是周五)。因为我们没有计算周五这一天(因为我们只加了5次,但是最后一天是周五,我们却忽略了?不对,最后一次我们加了三天(从周五到周六、周日、周一),所以最后是下周一。但是我们希望的是周五作为5个工作日后的结果。因此,我们需要修:当我们加了一天变成周五时,此时workingDays应该为0?不对,在第五次循环开始时,workingDays=1,我们加一天变成周二(第一次),然后第二次变周三,第三次变周四,第四次变周五(这时workingDays=0)?不对,我们循环5次,每次加一个工作日。正确的计算应该是:每个工作日加一次(相当于在日历上添加一个工作日)。但是,我们添加的这5个工作日分别是:周二、周三、周四、周五、下周一?所以多跨了一个周末。我们期望的5个工作日是:周二、周三、周四、周五、?不对,我们想要周五,但是周五已经是我们添加的第五个工作日(周二到周五只有4个工作日?)实际上,从当前时间(周一)开始,我们想要5个工作日之后,应该是从下一个工作日(周二)开始算第一个,然后第五个是周五(所以第五个工作日是周五)。所以循环5次,最后得到周五。因此,上述算法在周一运行,得到下周一是不对的。重新用周一测试算法:workingDays=5result=周一第1次:result=周二(工作日)->workingDays=4第2次:result=周三(工作日)->3第3次:周四->2第4次:周五->1第5次:加一天变成周六(跳过)->周日(跳过)->周一(下周一)->工作日,workingDays=0->结束。得到下周一。但期望是周五。所以我们需要修:当前时间如果是工作日,那么第一个工作日应该是当前日加1天(周二)?而最后的结果应该在周五结束(即第五次循环后应该是周五)。但是按照算法,我们只能得到下周一(因为我们加了5次,从周二到周五只有4天?不对,周二到周五是4个工作日(周二、三、四、五),所以我们在第5次循环时需要再跳到下周一。所以,如果我们希望从当前时间(周一)开始,加上5个工作日,应该等于下周一(因为周二、三、四、五、下周一,共5个工作日)。但是,实际上,5个工作日应该只需要5天(即到周五)吗?这5天就是周一到周五(5个工作日)。注意,我们是从当前时间开始计算,那么当前日(周一)算不算一个工作日?我们刚才的算法没有算。我们的算法中,我们是从当前时间的下一天开始计数的,所以忽略了当前日。因此,如果我们希望当前日(周一)作为第一个工作日,然后只需要再加4天(周二到周五)就可以得到第五个工作日(周五)。即:0:周一(当前日,不进入计数)1:周二(计1)2:周三(计2)3:周四(计3)4:周五(计4)然后循环结束,得到周五(因为我们需要4次循环)。因此,我们需要将工作日数设置为4?不行,因为用户要求加5个工作日。我们重新调整需求:我们要在“当前日期”的基础上加上5个工作日。当前日期如果是周一,那么加上5个工作日应该是周五(因为周一到周五就是5个工作日)。那么,我们就不应该跳过当前日,而是应该将当前日作为一个工作日(如果当前是工作日的话)。但是,我们的算法是从当前日期的下一天开始计算的,所以我们可以设置:如果当前日是工作日,那么我们直接从当前日开始计数?不对,我们算法是:我们加了1天后变成下一个自然日,然后判断这个自然日是不是工作日,是则计数。这个算法等价于:从当前日的下一天开始,寻找5个工作日(不包含当前日)。那么,我们想要包含当前日,该怎么办?我们可以变为:如果当前日是工作日,那么我们可以先减少一个工作日(因为当前日就算一个),然后从下一天开始再寻找4个工作日。但是,这种方法比较复杂。我们可以变算法:将当前日考虑进去,在循环之前先判断当前日是不是工作日,如果是,那么我们计数器就减少一个(代表当前日已经是一个工作日),然后在此基础上,我们再按照循环添加剩下的4个工作日(此时起点还是当前日,但是我们先减了计数器,然后加了一天开始)。这会导致代码复杂。另一种方案:修算法,让它可以包含起始日(如果起始日是工作日)。但是我们的需求是“加五个工作日”,并不是从下一个工作日开始计算。我们想要的是:T+0:如果T是工作日,那么第0天就是T。T+1:下一个工作日...T+4:第四个下一个工作日,总第五个工作日。所以,我们想要T+5(包含T)=T加上4个工作日(从T+1到T+4),再加上T本身?这样不对。我们使用一个新的方法:直接加5个工作日,包括起始日(如果起始日是工作日)。我们采用:workingDays=5;//先检查当前是不是工作日,如果是,则workingDays减一,并且//然后从当前日开始,循环直到workingDays为0,每次加1天,并跳过非工作日,遇到工作日则减1。//或者:我们从当前日开始,不断加一天,直到我们遇到了workingDays个工作日(包括当前日)但是我们希望的是“加5个工作日”,所以我们不希望变起始点的时间(例如,如果是周五,加5个工作日就要7天后),所以我倾向于://方案1:不包括当前日方案1(不包括当前日):我们加5个工作日(5个有效工作日)的时间点,一定是在当前日之后的5个工作日(无论当前日是不是工作日,我们都从下一天开始计算)。这样,如果当前是工作日,那么5个工作日后的日期=从下一个自然日开始,跳过周末,找到5个工作日。如果当前是非工作日,那么5个工作日后的日期=从下一个自然日开始,跳过周末,找到5个工作日。例如,周一加5个工作日:我们从下一个自然日(周二)开始计数,然后周三、周四、周五、下周一->5个工作日(下周一),结果时间就是下周一。例如,周五加5个工作日:下一个自然日是周六(跳过),周日(跳过),周一(计数1),周二(2),周三(3),周四(4),周五(5)->下周五。所以,无论当前日是什么,我们都是从下一天开始计数5次。//但是用户需求是“加五个工作日”,这种方式得到的结果对于周一来说是下周一(5天后)而不是周五(4天后),用户可能期望周五(因为他们知道周一到周五只有5天)。方案2(包括当前日):我们认为当前日算第0天,然后我们一共需要找5个工作日,但是我们希望从下一个自然日开始,每遇到一个工作日就计数,共5个工作日。这样,//0:当前日(如果当前是工作日,那么就是第0个工作日)//1:下一个工作日//计数1//2:计数2//...//5:第5个工作日所以,我们需要找5个“下一个”工作日。综合,我们发现金融界和用户的预期可能是“5个交易日后”https://en.wikipedia.org/wiki/T%2Bn其中T是交易日,所以T+0是T,T+1就是下一个交易日。所以我们加5个工作日应该不包括当前日(即从下一个交易日开始计数5个交易日)。因此,我们采用方案1(不包括当前日)的算法。但是,用户的具体需求是什么?我们看用户需求:“当前时间加五个工作日”->理解为:不管当前日是什么,我们从下一个自然日开始计数5个工作日。这样,周一:加5个工作日->1(周二)+2(周三)+3(周四)+4(周五)+5(下周一)->下周一周五:加5个工作日->1(下周一)+2(下周二)+3(下周三)+4(下周四)+5(下周五)->下周五因此,用户输入“2024-06-07(周五)15:00:00”,加5个工作日,结果就是“2024-06-1415:00:00”(因为6月7日是周五,下周一6月10日,下周五6月14日)这样实现代码:importjava.time.*;importjava.time.format.DateTimeFormatter;importjava.time.DayOfWeek;publicclassAddWorkingDays{publicstaticvoidmain(String[]args){//获取当前日期时间LocalDateTimecurrentDateTime=LocalDateTime.now();//需要添加的工作日数intworkingDays=5;LocalDateTimeresult=currentDateTime;while(workingDays>0){//每次先加一天result=result.plusDays(1);//检查是否是工作日(星期一到星期五)if(result.getDayOfWeek()!=DayOfWeek.SATURDAY&&result.getDayOfWeek()!=DayOfWeek.SUNDAY){workingDays--;//遇到工作日,才减去一个计数}}//格式化DateTimeFormatterformatter=DateTimeFormatter.ofPattern("yyyyMMddHHmmss");StringformattedDateTime=result.format(formatter);System.out.println("五个工作日后的时间是:"+formattedDateTime);}}注意:我们不考虑公历节日(比如五一长假),只考虑周末。测试:如果今天是周五(2024-06-07),那么加上5个工作日(跳过周六、周日),那么:第一次加1天:2024-06-08(周六)->非工作日,不计数(workingDays还是5)第二次加1天:2024-06-09(周日)->非工作日,不计数(5)第三次加1天:2024-06-10(周一)->工作日,计数减一(4)第四次加1天:2024-06-11(周二)->工作日,计数3第五次:6-12(周三)->2第六次:6-13(周四)->1第七次:6-14(周五)->0结束。所以结果日期是2024-06-14,并且时间部分与当前时间相同。符合预期。但是,我们也可以优化:不用多次加一天,可以判断如果某次加天后是周末,则可以跳过整个周末(比如遇到周六,直接加2天变成周一)?但是考虑到跨周末情况,以及闰年等,我们直接加一天然后判断比较安全。因此,我们就用上述代码。但是,还有一种情况:如果连续加很多天,可能性能不是问题(因为5次,最多加7天?)所以,就这样实现。另外,用户要的是字符串,所以最后格式化。代码实现:注意:如果当前时间包含毫秒、纳秒,但我们只需要到秒,所以格式化时只到秒(yyyyMMddHHmmss)。另外,我们的算法不会变时间(只变日期)。输出格式要求:年月日时分秒,没有连字符。编写代码:</think> 以下是获取当前时间五个工作日后并以字符串格式 `yyyyMMddHHmmss` 输出的 Java 实现代码: ```java import java.time.*; import java.time.format.DateTimeFormatter; import java.time.DayOfWeek; public class AddWorkingDays { public static void main(String[] args) { // 1. 获取当前日期时间 LocalDateTime currentDateTime = LocalDateTime.now(); // 2. 计算五个工作日后(跳过周末) int workingDaysToAdd = 5; LocalDateTime resultDateTime = currentDateTime; while (workingDaysToAdd > 0) { resultDateTime = resultDateTime.plusDays(1); // 增加1天 // 跳过周六/周日 if (resultDateTime.getDayOfWeek() != DayOfWeek.SATURDAY && resultDateTime.getDayOfWeek() != DayOfWeek.SUNDAY) { workingDaysToAdd--; // 仅在工作日减少计数 } } // 3. 格式化为 yyyyMMddHHmmss 字符串 DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMddHHmmss"); String formattedDateTime = resultDateTime.format(formatter); // 4. 输出结果 System.out.println("当前时间: " + currentDateTime.format(DateTimeFormatter.ISO_LOCAL_DATE_TIME)); System.out.println("五个工作日后: " + formattedDateTime); } } ``` ### 关键说明: 1. **工作日定义**: - 仅跳过周末(周六、周日),不考虑公共假日 - 通过 `DayOfWeek` 枚举检查工作日[^3] 2. **计算逻辑**: - 从当前时间开始(包含时分秒) - 每次循环增加1自然日 - 遇到非工作日(周末)不减少计数器 - 遇到工作日计数器减1,直到累计5个工作日 3. **时间处理**: - 使用 `java.time.LocalDateTime` 处理日期时间[^1] - 通过 `DateTimeFormatter` 指定输出格式[^1] 4. **输出示例**: ``` 当前时间: 2024-06-14T15:30:45.123456789 五个工作日后: 20240621153045 ``` ### 性能特点: - 时间复杂度:最坏情况(从周五开始计算)需要添加9自然日(5工作日+4周末) - 空间复杂度:O(1),仅需常量存储空间 ### 注意事项: 1. 如果需要考虑法定节假日,需引入外部日历服务 2. 对时间精度要求高时,建议明确时区设置,例如: ```java LocalDateTime.now(ZoneId.of("Asia/Shanghai")); ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值