创建一个 FY 为 'key' 和 Quarter 为 'value' - JavaScript 的对象

Creating an object with FY as 'key' and Quarter as 'value' - JavaScript

我正在尝试创建一个对象,其 'key' 将是财政年度 (FY),'values' 是季度日期。

//Format
{
   FY:{
        [Quarter dates]
   },
}

季度日期计数从1到4不等。如果只给出一个季度的信息,则以以前的财年为参考,加1就知道现在的财年。

我可以根据期间结束日期对季度进行分组,但计算财政年度是我需要的帮助。 FY 将遵循这些规则。

  1. 重复次数最多的季度将是财政年度。

  2. 如果季度有两个不同的年份,每个年份都是 2,那么我们可以选择最小的年份作为 FY。 例如:期间 =[06/21],季度 =[09/20,12/20,03/21,06/21] 那么 FY =2020

公司可以更改其期间结束日期,因此您可以预期季度日期之间存在差距。在以下示例中,公司使用 12 月作为期末,直到 2019 年,之后他们使用 3 月作为期末。省略了一个季度(一月、二月、三月)的差距。

const quarters = [
    "12 / 30 / 2021",
    "09 / 30 / 2021",
    "06 / 30 / 2021",
    "03 / 30 / 2021",
    "12 / 30 / 2020",
    "09 / 30 / 2020",
    "06 / 30 / 2020",
    "12 / 30 / 2019",
    "09 / 30 / 2019",
    "06 / 30 / 2019",
    "03 / 30 / 2019",
    "12 / 30 / 2018",
    "09 / 30 / 2018",
    "06 / 30 / 2018",
    "03 / 30 / 2018",
];
const periods = [
    "03 / 30 / 2021",
    "12 / 30 / 2019",
    "12 / 30 / 2018",
    "12/30/2017"
];

const groupQuarters = [];
let group = [];
while (periods.length > 0) {
    let p = new Date(periods[0].toString());
    group = [];
    while (quarters.length > 0) {
        let q = new Date(quarters[0].toString());
        if (q > p) {
            group.push(quarters[0]);
            quarters.shift();
        } else {
            break;
        }
    }
    const yearCal = (groups) => {
        // unable to figure this out.
        return 2020;
    }
    groupQuarters.push({ [yearCal(group)]: group });
    periods.shift();
}


console.log(groupQuarters);
Expected output:
[
  {
      2021: [
          '12 / 30 / 2021',
          '09 / 30 / 2021',
          '06 / 30 / 2021'
      ]
  },
  {
      2020: [
          '03 / 30 / 2021',
          '12 / 30 / 2020',
          '09 / 30 / 2020',
          '06 / 30 / 2020'
      ]
  },
  {
      2019: [
          '12 / 30 / 2019',
          '09 / 30 / 2019',
          '06 / 30 / 2019',
          '03 / 30 / 2019'
      ]
  },
  {
      2018: [
          '12 / 30 / 2018',
          '09 / 30 / 2018',
          '06 / 30 / 2018',
          '03 / 30 / 2018'
      ]
  }
]
Test Case - 2:
const quarters = [
  "12 / 30 / 2020",
  "09 / 30 / 2020",
  "06 / 30 / 2020",
  "03 / 30 / 2020",
  "12 / 30 / 2019",
  "09 / 30 / 2019",
  "06 / 30 / 2019",
  "03 / 30 / 2019",
  "12 / 30 / 2018"
];
const periods = [
  "09 / 30 / 2020",
  "09 / 30 / 2019",
  "09 / 30 / 2018",
];

Expected Output:
[
  {
    2021: [
      '12 / 30 / 2020',
    ]
  },
  {
    2020: [
      "09 / 30 / 2020",
      "06 / 30 / 2020",
      "03 / 30 / 2020",
      "12 / 30 / 2019",
    ]
  },
  {
    2019: [
      "09 / 30 / 2019",
      "06 / 30 / 2019",
      "03 / 30 / 2019",
      "12 / 30 / 2018",
    ]
  },
]

你可以试试:

const quarters = [
    "12 / 30 / 2021",
    "09 / 30 / 2021",
    "06 / 30 / 2021",
    "03 / 30 / 2021",
    "12 / 30 / 2020",
    "09 / 30 / 2020",
    "06 / 30 / 2020",
    "12 / 30 / 2019",
    "09 / 30 / 2019",
    "06 / 30 / 2019",
    "03 / 30 / 2019",
    "12 / 30 / 2018",
    "09 / 30 / 2018",
    "06 / 30 / 2018",
    "03 / 30 / 2018",
]
const periods = [
    "03 / 30 / 2021",
    "12 / 30 / 2019",
    "12 / 30 / 2018",
    "12/30/2017"
]
const quarters1 = [
  "12 / 30 / 2020",
  "09 / 30 / 2020",
  "06 / 30 / 2020",
  "03 / 30 / 2020",
  "12 / 30 / 2019",
  "09 / 30 / 2019",
  "06 / 30 / 2019",
  "03 / 30 / 2019",
  "12 / 30 / 2018"
];
const periods1 = [
  "09 / 30 / 2020",
  "09 / 30 / 2019",
  "09 / 30 / 2018",
];
const getGroupQuarter = (qt, pr) => {
  let tmpCheck = qt
  return pr.reduce((result,period) => {
    let datePeriod = new Date(period)
    let key = getKeyQuarter(datePeriod)
    let qtrFill =  tmpCheck.filter(quarter => new Date(quarter) > datePeriod)
    tmpCheck =  tmpCheck.filter(quarter =>!(new Date(quarter) > datePeriod))
    return !qtrFill.length ? result :[...result, {[key] : qtrFill}]
  }, [])
}
const getKeyQuarter = (pr) => {
  let monthValidate = pr.getMonth()
  return monthValidate > 5 ? pr.getFullYear() + 1 : pr.getFullYear()
}
console.log(getGroupQuarter(quarters1, periods1));
console.log(getGroupQuarter(quarters, periods));

假设在一个时期内没有差距——即属于同一时期的两个季度之间没有差距——你可以应用这个逻辑:

  • 当知道期间的最后一个季度(即它等于 period-end)时,减去 2 个季度并将该季度的年份作为财政年度
  • 当周期的最后一个季度未知时——这可能发生在数组的开头,当前周期尚未完成——在该周期的第一季度添加四分之一并取它季度作为财政年度。

因为 map periods 数组 one-to-one 以获得结果数组很好,有时可能需要去除最后一个周期条目(就像在测试用例 1 中一样),或者在该数组的开头插入一个未完成的句点(也在测试用例 1 中)。

不相关,但我为此任务避免了 Date 对象,并包含将输入字符串转换为数字并返回的函数:

function chunkByYear(quarters, periods) {
    // Converter functions between string and unique quarter number
    const toQuarter = s => s.match(/^\d+|\d+$/g).reduce((m, y) => m/3 - 1 + y*4);
    const toDate = q => ((q % 4 + 1)*3 + "/30/" + (q >> 2)).padStart(10, "0");

    const periodNums = periods.map(toQuarter);
    const quarterNums = quarters.map(toQuarter);
    // Make sure all quarters are after at least one period end
    while (quarterNums[quarterNums.length-1] <= periodNums[periodNums.length-1]) periodNums.push(periodNums[periodNums.length-1] - 4);
    // Remove periods that have no content:
    while (quarterNums[0] <= periodNums[0]) periodNums.shift();
    quarterNums.push(0); // To make sure `findIndex` always finds an index
    return periodNums.map((p, i, {length}) => {
        const period = quarterNums.splice(0, quarterNums.findIndex(q => q <= p));
        return { [(i ? period[0] - 2 : period[period.length-1] + 1) >> 2]: period.map(toDate) };
    });
}

{ // test 1
    const quarters = [
        "12 / 30 / 2021", "09 / 30 / 2021", "06 / 30 / 2021",
        "03 / 30 / 2021", "12 / 30 / 2020", "09 / 30 / 2020", "06 / 30 / 2020",
        "12 / 30 / 2019", "09 / 30 / 2019", "06 / 30 / 2019", "03 / 30 / 2019",
        "12 / 30 / 2018", "09 / 30 / 2018", "06 / 30 / 2018", "03 / 30 / 2018",
    ];
    const periods =  ["03 / 30 / 2021", "12 / 30 / 2019", "12 / 30 / 2018", "12 / 30 / 2017"];
    console.log(chunkByYear(quarters, periods));
}
{ // test 2
    const quarters = [
        "12 / 30 / 2020",
        "09 / 30 / 2020", "06 / 30 / 2020", "03 / 30 / 2020", "12 / 30 / 2019",
        "09 / 30 / 2019", "06 / 30 / 2019", "03 / 30 / 2019", "12 / 30 / 2018"
    ];
    const periods =  ["09 / 30 / 2020", "09 / 30 / 2019", "09 / 30 / 2018"];
    console.log(chunkByYear(quarters, periods));
}
{ // test 3
    const quarters = [
        "06 / 30 / 2021", "03 / 30 / 2021", "12 / 30 / 2020", "09 / 30 / 2020",
        "06 / 30 / 2020", "03 / 30 / 2020", "12 / 30 / 2019", "09 / 30 / 2019",
        "06 / 30 / 2019",
    ];
    const periods = ["06 / 30 / 2021", "06 / 30 / 2020", "06 / 30 / 2019"];
    console.log(chunkByYear(quarters, periods));
}
{ // test 4
    const quarters = [
        "06 / 30 / 2021", "03 / 30 / 2021", "12 / 30 / 2020", "09 / 30 / 2020",
        "06 / 31 / 2020", "03 / 30 / 2020", "12 / 30 / 2019", "09 / 30 / 2019",
        "06 / 30 / 2019", "03 / 30 / 2019", "12 / 30 / 2018", "09 / 30 / 2018",
    ];
    const periods = ["06 / 30 / 2021", "06 / 31 / 2020", "06 / 30 / 2019"];
    console.log(chunkByYear(quarters, periods));
}