如何在javascript中处理时区

时间:2016-02-17 05:08:43

标签: javascript node.js date

我正在做一个从控制台运行的应用程序,它计算在过去的日期之间的每个月中的星期日数,并且仅在5个星期日输出几个月。所以最后如果有6个月有5个星期日,则输出6.我以这种格式输入日期:2014年1月2014年,并且params在作为参数传递的txt文件中。我在php中做到了这很简单,但在节点js中,我很痛苦。 CES或CEST正在扼杀我。我只是尝试使用UTC日期,但我无法控制它并且我有奇怪的输出。例如,如果我介绍" 2014年1月2014"我得到两个月,但是当我介绍" 2016年6月和2017年2月"我得到4,应该是3。 当程序计算五个星期日时,我放了一个console.log(日期),我得到了那些日期:

Sun Mar 30 2014 00:00:00 GMT+0100 (CET)
Sun Jun 01 2014 01:00:00 GMT+0200 (CEST)
2 //the output of months that have 5 sundays

Sun Jul 31 2016 00:00:00 GMT+0200 (CEST)
Sun Oct 30 2016 00:00:00 GMT+0200 (CEST)
Sat Dec 31 2016 23:00:00 GMT+0100 (CET)
Sat Feb 04 2017 23:00:00 GMT+0100 (CET)
4  //the output of months that have 5 sundays

如你所见,有两个星期六,格林威治标准时间23:00:00 + 0100(CET)。这个输出很奇怪,我真的不知道如何处理这个问题。任何帮助,将不胜感激。

// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
  console.log('Usage: node ' + process.argv[1] + ' FILENAME');
  process.exit(1);
}
// Read the file and print its contents.
var fs = require('fs'), filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
    if (err) throw err;
    //split by carriage return
    data = data.split(/[\n\r]+/g);

    data.forEach(function(value){
        var secureDate = securizeData(value);
        var totalDays = getDaysBetweenDates(secureDate[0],secureDate[1],secureDate[2],secureDate[3]);
        calculateSundays(totalDays, secureDate[0],secureDate[1])    
    });

});

/**
 * Description: checks the data and returns it as an array
 * @param {string} data
 * @return {array} data
 */
function securizeData(data){

    //Looks for two strings (months) and two int ( year) matches with regexp 
    var matchCount = data.match(/([a-z]+ [0-9]{4})/g);
    if(matchCount == 0){
        process.exit('Insert a valid input');
    }

    //clean carriage return
    data = data.replace(/[\n\r]+/g,' ',data);
    //clean left over blank spaces
    data = data.replace(/  +/g,' ',data);


    //split data in an array
    data = data.split(' ');

    //check array length
    var nIndex = data.length;

    //returns an array which it's total index number is a pair number or else error
    if(nIndex%2==0){
        return (data);
    }else{
        process.exit('Insert a valid input');
    }
}

/**
 * Description:
 * @param {string} firstMonth
 * @param {int} firstYear
 * @param {string} secondMonth
 * @param {int} secondYear 
 */
function getDaysBetweenDates(firstMonth, firstYear, secondMonth, secondYear){

        var daysFirstDate = getDaysFirstDate(firstMonth, firstYear);
        var daysSecondDate =  getDaysSecondDate(secondMonth,secondYear);
        var daysBetweenDates = substractDays(daysFirstDate,daysSecondDate);
        return daysBetweenDates; 
}

/**
 * Description: substraction of two given unix dates
 * @param {int} daysFirstDate
 * @param {int} daysSecondDate
 * @return {int} days in unix format. Error if first date is later than second 
 */
function substractDays(daysFirstDate,daysSecondDate){

    if(daysFirstDate>daysSecondDate){
        process.exit('First date must be earlier than second date');
    }else{
        var datediff = daysSecondDate-daysFirstDate;
        datediff = datediff/(60*60*24)/1000;
        var roundedNumber = Math.floor(datediff)
        return (roundedNumber);
    }   
}

/**
 * Description: get the first date from day one in unix format
 * @param {string} @firstMonth
 * @param {int} @firstYear
 * @return {int} @date
 */
function getDaysFirstDate(firstMonth,firstYear){
    var month = getMonthFromString(firstMonth,firstYear);
    return (Date.UTC(firstYear, month ,01));
}

/**
 * Description: get the second date from last day of it's month in unix format
 * @param {string} @secondMonth
 * @param {int} @secondYear
 * @return {int} @date2
 */
function getDaysSecondDate(secondMonth,secondYear){

        var secondMonthNumber = getMonthFromString(secondMonth,secondYear);

        //Get last day of the month
        var lastDayMonth = getLastDayOfTheMonth(secondMonthNumber,secondYear);

        //Add last day of the month to secondDate
        return (Date.parse(secondMonth + ' ' + lastDayMonth +', ' + secondYear));

}

/**
 * Description: get month number from a month string
 * @param {string} @month
 * @return {int} @month
 */
function getMonthFromString(mon,year){
   return new Date(Date.parse(mon +" 1, "+year)).getMonth();
}

/**
 * Description: get the Last day of the Month given in params
 * @param {int} @secondYear
 * @param {int} @secondMonthNumber
 * @return {int} UTCDate
 *
 */
function getLastDayOfTheMonth(secondMonthNumber, secondYear){
    var lastDay = new Date(secondYear, secondMonthNumber +1, 0);
    return(lastDay.getUTCDate());
}

/**
 * Description:
 * @param {int} totalDays
 * @param {array} tempDate
 */
function calculateSundays(totalDays,month, year){

    var sundays={ num: '0' , output: '0' };
    var intMonth = { val: new Date(Date.parse(month + year)).getMonth() };
    intMonth.previousVal = intMonth.val;

    var d = Math.floor((new Date(year, intMonth.val,1)).getTime());
/// console.log(e);
//  process.exit();

    var d = new Date(year, intMonth.val, 1);
    var dayOfTheWeek = d.getUTCDay();

    for(var day = 2;day<=totalDays;day++)
    {

        resetSundaysIfMonthIncrease(intMonth, sundays);

        //update sundays
        if(dayOfTheWeek == 6) {
            sundays.num++;
        }

        //if there is 5 days in a month increase output
        if(sundays.num == 5)
        {
            sundays.output++;
            sundays.num = 0;
            console.log(d);
        }

        //increment date
        d.setUTCDate(d.getUTCDate() + 1);

        //update Day of the week
        dayOfTheWeek = d.getUTCDay();

        //update Month
        intMonth.val = d.getUTCMonth();
    }

    if(sundays.output == 0)process.exit("Please enter more than one month distance between dates \n");
    else console.log(sundays.output + "\n");
}  

/**
 * description: reset sunday counter to 0 if current month is greater than previous month 
 * @param {Object} intMonth
 * @param {Object} sundays
 */
function resetSundaysIfMonthIncrease(intMonth, sundays)
{   
    if(intMonth.val>intMonth.previousVal)
    {
        intMonth.previousVal = intMonth.val;
        sundays.num = 0;
    }
}

2 个答案:

答案 0 :(得分:2)

一个简单的算法是获取当月的第一个星期日,看看它是否在本月底之前不到28天。如果是这样,月份有4个星期日,否则5. UTC无关紧要。

这里有一些代码,希望评论足够:

&#13;
&#13;
/* Return the number of months with 5 sundays between two dates
** specified as year, month where month number is the calendar month,
** Jan = 1, Feb - 2, etc.
**
** @param {number} y0 - start year
** @param {number} y1 - end year
** @param {number} m0 - start month (calendar number)
** @param {number} m1 - end month (calendar number) 
** @returns {number} number of months with 5 Sundays between start and end
*/
function countMonthsWith5Sundays(y0, m0, y1, m1) {
  
  // Create dates for first of start and end month
  var start = new Date(y0, m0-1, 1);
  var end = new Date(y1, m1-1, 1);
  var count = 0;
  
  // If end is before start, swap dates
  if (start > end) {
    var t = start;
	start = end;
	end = t;
  }
  
  // Step month by month from start to end, counting months with 5 Sundays
  while (start <= end) {
    if (sundaysInMonth(start.getFullYear(), start.getMonth() + 1) === 5) {
	  ++count;
	}
	start.setMonth(start.getMonth() + 1);
  }
  return count;
}

// Month number is calendar month, jan = 1, feb = 2, etc.
/* Calculate number of Sundays in a month
**
** @param {number} y - year
** @param {number} m - month number (calendar number)
*/
function sundaysInMonth(y, m) {
  // Create date for start of month, move to first Sunday
  var d = new Date(y, m-1, 1);
  d.setDate(d.getDate() + (d.getDay()? 7 - d.getDay() : 0));
  
  // Get number of days in month, subtract current date and
  // if there are 28 days or more left, there are 5 Sundays
  // Use calendar month number and date of 0 to get last day of
  // month
  var daysInMonth = new Date(y, m, 0).getDate();
  return daysInMonth - d.getDate() > 27 ? 5 : 4;
}

document.write(countMonthsWith5Sundays(2016,1,2016,6));
&#13;
&#13;
&#13;

上述内容可以轻松修改,以便在有5个星期日的月份中返回代表第一天或第一个星期日的日期。

答案 1 :(得分:0)

似乎列出有5个星期日的月份的解决方案围绕2条规则:

  1. 月份应该超过28天;和
  2. 第一个星期日的日期应该少于本月28日以上的天数。
  3. 我修改了您的代码以使用moment.js

    看起来像是:

    // Make sure we got a filename on the command line.
    if (process.argv.length < 3) {
      console.log('Usage: node ' + process.argv[1] + ' FILENAME');
      process.exit(1);
    }
    
    // Read the file and print its contents.
    var fs = require('fs'), filename = process.argv[2];
    fs.readFile(filename, 'utf8', function(err, data) {
      if (err) throw err;
      //split by carriage return
      data = data.split(/[\n\r]+/g);
    
      data.forEach(function(value){
        var secureDate = securizeData(value);
        calcSundays(secureDate[0], secureDate[1], secureDate[2], secureDate[3]);
      });
    });
    
    /**
     * Description: checks the data and returns it as an array
     * @param {string} data
     * @return {array} data
     */
    function securizeData(data){
      //Looks for two strings (months) and two int ( year) matches with regexp 
      var matchCount = data.match(/([a-z]+ [0-9]{4})/g);
      if(matchCount == 0){
        process.exit('Insert a valid input');
      }
    
      //clean carriage return
      data = data.replace(/[\n\r]+/g,' ',data);
      //clean left over blank spaces
      data = data.replace(/  +/g,' ',data);
    
      //split data in an array
      data = data.split(' ');
    
      //check array length
      var nIndex = data.length;
    
      //returns an array which it's total index number is a pair number or else error
      if(nIndex%2==0){
        return (data);
      }else{
        process.exit('Insert a valid input');
      }
    }
    
    /**
     * Description: loop through the months between the start and end dates and count the sundays in each month.
     * @param {string} firstMonth
     * @param {int} firstYear
     * @param {string} secondMonth
     * @param {int} secondYear 
     */
    function calcSundays(startMonth, startYear, endMonth, endYear) {
      var intStartMonth = getMonthFromString(startMonth, startYear);
      var intEndMonth = getMonthFromString(endMonth, endYear);
      var date = { 
        month: intStartMonth, 
        year: startYear 
      };
    	
      while (date.month <= intEndMonth && date.year <= endYear) {
        var sundays = countSundaysInMonth(date);
        if (sundays == 5) {
          // Log the last sunday of the month with 5 sundays.
          console.log(moment(date).endOf('month').day(-7).format()); 
        }
      }
    }
    
    /**
     * Description: count the number of sundays in a month.
     * @param {object} date
     */
    function countSundaysInMonth(date) {
      var totDays = moment(date).endOf('month').date();
      if (totDays < 29) return 4;
      var firstSunday = moment(date).day('Sunday').date();
      if (firstSunday <= totDays - 28) return 5;
      return 4;
    }
    
    /**
     * Description: get month number from a month string
     * @param {string} @month
     * @return {int} @month
     */
    function getMonthFromString(mon,year){
      return new Date(Date.parse(mon +" 1, "+year)).getMonth();
    }