提问者:小点点

GAS函数返回错误的日期-是我还是缺陷?


除非我使用. toLocaleDateString()方法,否则下面的函数返回的日期比应该少一天。我做错了什么还是这是一个缺陷?

    function myDate() {
  var sDate = '05/10/2012';
  var parts = sDate.split('/');
  var d = new Date( parts[2], parts[1]-1, parts[0]);
  Logger.log(d);
  Logger.log(d.toLocaleDateString());
};

记录器返回:

Thu Oct 04 16:00:00 PDT 2012

2012年10月5日00:00:00英国夏令时

我在UK,因此日期格式UK。我已经检查了我的项目属性的时区设置为“(GMT00:00)伦敦”,那么为什么记录器在PDT中显示第一个日期呢?这是错误日期的原因吗?我已经在一个独立的项目中重现了这个问题。这是它的链接。

我想将字符串变量转换为日期对象以进行一些日期数学运算,因此必须使用. toLocaleDateString()方法转换回字符串是没有帮助的。

我已经检查了一致性,想也许我可以通过测试其他日期来解决它。奇怪的是,如果我将sDate的值更改为2012年1月1日之间的任何值


共3个答案

匿名用户

我发现在旧的DST规则和新的DST规则之间的范围内,getValue()函数读取的日期减少了1小时。因此,日期"10/30/2012"的隐式时间是00:00:00。但是,当读取时,它减少了一个小时,将其放在前一天,即10/29/2012 23:00:00。

这两个时间范围之间的任何日期,不包括开始日,但包括结束日,目前都将表现出此行为,至少在getValue()函数中是这样的:

  • 在十月的最后一个星期日到十一月的第一个星期日之间
  • 在三月的第二个星期日和四月的第一个星期日之间。

我最终编写了代码,可以动态计算当前年份的这些日期,如果日期落在目标范围内,我只需将其增加一个小时。这可能是修复它的漫长道路,但它是有效的。

这是我的代码:

/*
The old rules for DST stated that the time change occurred on the last Sunday in October, 
which would be 10/28/2012.  So, when you type in 10/29/2012, the timestamp associated with the date (00:00:00) is being decremented by an hour (23:00:00), 
which drops it into the previous day.  The new rules for DST states that DST ends on the 1st Sunday in November, which is 11/04/2012.  Also, the DST rules
for springtime are also an impacted range of dates that exhibit this behavior, between the second sunday in March and the first sunday in April.

Note:  Running this function from the script editor does not produce the strange DST behavior.  It seems to be an issue with the getValues() function on a Range object.
*/
function fixDateDSTProblem(lstrDate){
  var d = new Date(lstrDate);
  //Example ranges affected
  //10/29/2012 - 11/04/2012
  //03/11/2013 - 04/07/2013

  if(isNaN(d.getMonth())){
    //return what was passed in if it's not a date or null.
    return lstrDate;
  }
  else if(isAffectedDate(d)){
    //increment by one hour
    return new Date(d.getTime() + (60 * 60 * 1000));
  }
  else{
    //date is not affected, simply return it as it was passed.
    return lstrDate;
  }
}



//Check to see if a date is within a beginning and end date
function dateWithin(beginDate,endDate,checkDate) {
    var b,e,c;
    b = Date.parse(beginDate);
    e = Date.parse(endDate);
    c = Date.parse(checkDate);
  //slightly modified this for the date checking since beginning date is not inclusive, so needs to be > instead of >=
    if((c <= e && c > b)) {
            return true;
    }
    return false;
}



function isAffectedDate(targetDate){
  var yearNum = targetDate.getFullYear();

  //Get the last Sunday in October
  var lastSunOctDateStr = getLastOccurrenceDate(0, 10, yearNum);

  //Get the first Sunday in November
  var firstSunNovDateStr = getOccurrenceDate(1, 0, 11, yearNum);

  //Get the second Sunday in March
  var secondSunMarDateStr = getOccurrenceDate(2, 0, 3, yearNum);

  //Get the first Sunday in April
  var firstSunAprDateStr = getOccurrenceDate(1, 0, 4, yearNum);  


  //if the date is between the last sunday in october and the first sunday in november
  // or if the date is between the second sunday in march and the first sunday and april, fix it up!
  if(dateWithin(lastSunOctDateStr, firstSunNovDateStr, targetDate) || 
     dateWithin(secondSunMarDateStr, firstSunAprDateStr, targetDate)){
    return true;
  }
  return false;
}



function getOccurrenceDate(numOccurrence, dayIndex, monthCalendar, yearNum){
  //"Get date of first occurrence of Monday in June 2013"
  //"Get date of the second occurrence of Sunday in April 2013"
  //dayIndex:  Sunday = 0, Saturday = 6
  var monthIndex = monthCalendar - 1;
  var numFirstXDay = null;
  var firstDay = new Date(monthCalendar+"/01/"+yearNum);
  var numDayOfWeek = firstDay.getDay();
  if(numDayOfWeek == dayIndex){
    numFirstXDay = 1;
  }
  else if(numDayOfWeek > dayIndex){  
    numFirstXDay = 1+(6-numDayOfWeek)+1+dayIndex+(7*(numOccurrence-1));
  }
  else if(numDayOfWeek < dayIndex){
    numFirstXDay = 1+(dayIndex - numDayOfWeek)+(7*(numOccurrence-1));
  }

  return monthCalendar+"/"+numFirstXDay+"/"+yearNum; 
}



function getLastOccurrenceDate(dayIndex, monthCalendar, yearNum){
  //Example:  "Get date of last occurrence of Monday in June 2013"
  var monthIndex = monthCalendar - 1;
  var numLastXDay = null;
  //TODO:  Handle Leap Year!
  var monthMaxDaysArray = {
    '1':'31',
    '2':'28',
    '3':'31',
    '4':'30',
    '5':'31',
    '6':'30',
    '7':'31',
    '8':'31',
    '9':'30',
    '10':'31',
    '11':'30',
    '12':'31'}    

  var lastDay = new Date(monthCalendar + "/"+monthMaxDaysArray[monthCalendar]+"/" + yearNum);
  var numDayOfWeek = lastDay.getDay();
  if(numDayOfWeek == dayIndex){ 
    numLastXDay = 31;
  }
  else if(numDayOfWeek > dayIndex){    
   numLastXDay = monthMaxDaysArray[monthCalendar] - (numDayOfWeek - dayIndex); 
  }
  else if(numDayOfWeek < dayIndex){
    numLastXDay = (monthMaxDaysArray[monthCalendar] - numDayOfWeek) - (6 - (dayIndex-1));
  }

  return monthCalendar + "/" + numLastXDay + "/" + yearNum;
}

匿名用户

记录器总是记录PDT中的日期。这是相同的时间实例,只是表示方式不同。您可以看到夏令时的差异。

匿名用户

即使科里的回答不需要任何确认(他知道自己在说什么;)让我补充一些实际的细节…

    null

*编辑*几周以来语法发生了变化,这个字符串的格式必须不同,所以我相应地更新了这段代码。(见问题2204)

`var FUS1=new Date().toString().substr(25,6)+":00";// FUS1 gets the GMT+02:00 or GMT+01:00 string`

希望它足够清晰