2016-05-24 2 views
0

Я пытаюсь создать функцию, которая будет принимать три входные переменные (дата начала, дата окончания, зернистость) и выведет массив со всеми датами между ними. Выход будет либо ежедневной, либо ежемесячной детализацией на основе ввода. Например, если я смотрю на январь 2015 - февраль 2015:Javascript массив обеспечивает все дни/месяцы между двумя диапазонами дат

  • Ежемесячно будет [2015-01, 2015-02]
  • Ежедневно будет [2015-01-01, 2015-01- 02, 2015-01-03, ...., 2015-02-27, 2015-02-28]

Я закодировал что-то, основанное на некоторых других сообщениях, и логически кажется, что он должен работать я, но по какой-то причине, глядя на ежедневную гранулярность, каждый месяц возвращается с 31 днем. В приведенном ниже скрипте рассматривается только ежедневная гранулярность (ежемесячно будет легче сделать) - может кто-то взглянуть и посмотреть, что я делаю неправильно, и если есть более эффективный способ сделать это?

Входной формат дат «гггг-мм»

Я понимаю, что это, вероятно, новобранец ошибка, но, по крайней мере, я буду учиться :)

Благодаря

function dateRange2 (startDate,endDate,granularity) { 

    var dates = []; 
    var d0 = startDate.split('-'); 
    var d1 = endDate.split('-'); 
    var months31 = [1,3,5,7,8,10,12]; 
    var months30 = [4,6,9,11]; 


    for (var y = d0[0]; y <= d1[0]; y++) { 
     for (var m = d0[1]; m <= d1[1]; m++) { 
      if (m in months31) { 
       for (var d =1;d <=31; d++) { 
        dates.push(y+"-"+m+"-"+d); 
       } 
      } ///// Issue seems to be here - not switching over to next clause 
      else if (m in months30) { 
       for (var d =1; d <=30; d++) { 
        dates.push(y+"-"+m+"-"+d); 
       } 
      } else if (m=2 && y=2016) { 
       for (var d =1; d <=29; d++) { 
        dates.push(y+"-"+m+"-"+d); 
       } 
      } else if (m=2 && y!=2016) { 
       for (var d =1; d <=28; d++) { 
        dates.push(y+"-"+m+"-"+d); 
       } 
      }   
     } 
    } 
    return dates; 
} 
+0

попробуйте использовать '.contains' вместо' .indexOf' – Quill

ответ

2

вместо в операторе используйте indexOf, как показано ниже:

if (months31.indexOf(m) >= 0){ 
} 
else if (months30.index(m) >= 0){ 
} 

Оператор вернет ли данное значение является собственностью объекта или нет: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/in

+0

Спасибо за ответ. Пробовал это, и я получал [2016-2016-1, 2016-2016-2 ...., 2016-2016-29] для нескольких разных выходов. Даже если это не сработает, я сейчас рассмотрю эту функцию. EDIT: Собственно, даже с моей исходной формулой я получаю приведенные выше результаты, если я ввожу ошибочные результаты (т. Е. Месяц 13), поэтому я рассмотрю это немного больше –

0

Приведено в действие после проб и ошибок - это может быть не самый красивый код, но он выполняет эту работу ... в идеале я бы добавил каждую прокомментированную строку как часть отдельная функция.

Я также заметил, что каждый случай работает с использованием четырех аргументов «если», не требуя «else if».

function dateRangetest (start_month,start_year,end_month,end_year,granularity) { 

var dates = []; 
var d0 = [start_year,start_month]; 
var d1 = [end_year,end_month]; 

// var d0 = [2014,6]  FOR TESTING 
// var d1 = [2016,4] 

    switch (granularity) { 
    case "Daily": 
     for (var y = d0[0]; y <= d1[0]; y++) { 
     if ((y == d0[0]) && (d0[0] != d1[0])) {  // if year=start_year && year != end year ... start from start_month and loop up to month 12 
      for (var m = d0[1]; m <= 12; m++) {  
      for (var d =1;d <= monthday(m,y); d++) { 
       dates.push(y+"-"+m+"-"+d) 
      } 
      } 
     } 
     if ((y != d0[0]) && (y!= d1[0])) {   // if year != start_year && year != end year .... start from month 1 to month 12 - this would 2015 data in pulling Dec 2014 - April 2016 
      for (var m = 1; m <= 12; m++) {  
      for (var d =1;d <= monthday(m,y); d++) { 
       dates.push(y+"-"+m+"-"+d) 
      } 
      } 
     } 
     if ((y != d0[0]) && (y == d1[0])) {  // if year !=start_year && year = end_year .... start from month 1 up until end_month 
      for (var m = 1; m <= d1[1]; m++) {  
      for (var d =1;d <= monthday(m,y); d++) { 
       dates.push(y+"-"+m+"-"+d) 
      } 
      } 
     } 

     if ((y == d0[0]) && (y == d1[0])) {  /// if year=start_year && year = end_year .... start from start_month to end_month 
      for (var m = d0[1]; m <= d1[1]; m++) {  
      for (var d =1;d <= monthday(m,y); d++) { 
       dates.push(y+"-"+m+"-"+d) 
      } 
      } 
     } 
     } 
     break; 
    case "Monthly": 
     for (var y = d0[0]; y <= d1[0]; y++) { 
     if ((y == d0[0]) && (d0[0] != d1[0])) {  // if year=start_year && year != end year ... start from start_month and loop up to month 12 
      for (var m = d0[1]; m <= 12; m++) { 
      dates.push(y+"-"+m) 
      } 
     } 
     if ((y != d0[0]) && (y!= d1[0])) {   // if year != start_year && year != end year .... start from month 1 to month 12 - this would 2015 data in pulling Dec 2014 - April 2016 
      for (var m = 1; m <= 12; m++) { 
      dates.push(y+"-"+m) 
      } 
     } 
     if ((y != d0[0]) && (y == d1[0])) {  // if year !=start_year && year = end_year .... start from month 1 up until end_month 
      for (var m = 1; m <= d1[1]; m++) { 
      dates.push(y+"-"+m) 
      } 
     } 

     if ((y == d0[0]) && (y == d1[0])) {  /// if year=start_year && year = end_year .... start from start_month to end_month 
      for (var m = d0[1]; m <= d1[1]; m++) { 
      dates.push(y+"-"+m) 
      } 
     } 
     } 
    } 
    return dates 
} 

/// Function for Day Date Range 
function monthday (month,year) { 
var months31 = [1,3,5,7,8,10,12] 
var months30 = [4,6,9,11] 
var leapyear = [2016,2020,2024,2028,2032] 

if (months31.indexOf(month) >=0){ 
    var result = 31} 
    else if (months30.indexOf(month) >=0){ 
    var result = 30} 
    else if (month==2 && leapyear.indexOf(year) >=0){ 
    var result = 29} 
    else if (month==2 && year != 2016){ 
    var result = 28} 

    return result 
} 
1

Другие показали, как исправить ваш код. Отвечать «более эффективно» сложно, так как вы не предоставили для этого критериев. Но если вам нужен надежный код с разделением проблем, рассмотрите отдельные функции для синтаксического анализа строк даты, форматирования дат и расчета диапазонов.

Существует множество небольших библиотек для синтаксического анализа и дат форматирования, которые удобны, если у вас есть много разных форматов для размещения, но если нет, то должны подойти следующие простые функции.

Если документации и комментариев достаточно, спросите, и я предоставил вам обновления.

/* Parse date string in ISO 8601 format as local 
 
** @param {string} s - Date string like 2016-04-01 
 
** @returns {Date} If date is invalid, returns an invalid Date 
 
*/ 
 
function parseISODate(s) { 
 
    var b = s.split(/\D/); 
 
    var d = new Date(b[0], b[1]? b[1] - 1 : 0, b[2] || 1); 
 
    return d && d.getMonth() == b[1] - 1? d : new Date(NaN); 
 
} 
 

 
/* Return an ISO 8601 formatted date string based on local time 
 
** Only works for positive years (i.e. doesn't do -ve year) 
 
** @param {Date} date - date object to create date string from 
 
** @returns {string} dates string in yyyy-mm-dd format or default from 
 
**     Date.prototype.toString (i.e. "Invalid Date") 
 
*/ 
 
function toISODate(date) { 
 
    return date.getDate()? ('000' + date.getFullYear()).slice(-4) + '-' + 
 
         ('0' + (date.getMonth() + 1)).slice(-2) + '-' + 
 
         ('0' + date.getDate()).slice(-2) : date.toString(); 
 
} 
 

 
/* Generate an array of ISO 8601 formatted date strings for a 
 
** range of dates inclusive of start and end. Either monthly 
 
** or daily intervals (default is daily). 
 
** @param {string} fromDate - start date in ISO 8601 format 
 
** @param {string} toDate - end date in ISO 8601 format 
 
** @param {boolean} monthly - return monthly intervals 
 
** @returns {Array} of date strings. If either fromDate or 
 
**     toDate are invalid, returns undefined. 
 
*/ 
 
function genDatesInRange(fromDate, toDate, monthly) { 
 
    var s = parseISODate(fromDate); 
 
    var e = parseISODate(toDate); 
 
    var dates = []; 
 

 
    // Check that dates are valid 
 
    if (!s.getDate() || !e.getDate()) return; 
 

 
    // If monthly, set start to 1st of start month and e to 1st of end month 
 
    if (monthly) { 
 
    s.setDate(1); 
 
    e.setDate(1); 
 
    } 
 

 
    while (s <= e) { 
 
    dates.push(monthly? toISODate(s).substr(0,7) : toISODate(s)); 
 
    if (monthly) { 
 
     s.setMonth(s.getMonth() + 1); 
 
    } else { 
 
     s.setDate(s.getDate() + 1); 
 
    } 
 
    } 
 
    return dates; 
 
} 
 

 
// Daily 
 
console.log(genDatesInRange('2015-05-23','2015-06-03'));  // Daily 
 
console.log(genDatesInRange('2015-09-03','2016-03-13', true)); // Monthly

Смежные вопросы