除非我使用. 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日之间的任何值
我发现在旧的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中的日期。这是相同的时间实例,只是表示方式不同。您可以看到夏令时的差异。
即使科里的回答不需要任何确认(他知道自己在说什么;)让我补充一些实际的细节…
*编辑*几周以来语法发生了变化,这个字符串的格式必须不同,所以我相应地更新了这段代码。(见问题2204)
`var FUS1=new Date().toString().substr(25,6)+":00";// FUS1 gets the GMT+02:00 or GMT+01:00 string`
希望它足够清晰