Javascript循环并在对象中组合日期

时间:2022-11-29 20:51:38

I need help with something that might be a common problem and something that others would benefit from as well, which is to modify dates in an object and combine them into a chronological list. The overall goal is to create a list which reflects all of the upcoming special dates in a year:

我需要帮助处理可能是常见问题的事情以及其他人也可以从中受益的事情,即修改对象中的日期并将它们组合成按时间顺序排列的列表。总体目标是创建一个列表,反映一年中所有即将到来的特殊日期:

1 Jan - Sharpe's Anniversary
2 May - Edward's Birthday
12 Dec - Zero's Anniversary
etc...

I began by creating an object to represent this. Then slice out the year so that a comparison won't just arrange them by their order of initial occurrence, but will give an annual basis. Then perform a comparison to arrange the dates in chronological order. Then log out the result with the matching person's identity.

我开始创建一个对象来代表这个。然后切出年份,以便比较不仅按照他们的初始发生顺序排列它们,而且会给出年度基础。然后执行比较以按时间顺序排列日期。然后使用匹配的人的身份注销结果。

Up to this point I got it to work. However, I do not know how to repeat this and make it DRY. Certainly it would be sloppy to run this for anniversaries, then for birthdays without making some sort of custom function. All my attempts have not ended successfully.

到目前为止,我得到了它的工作。但是,我不知道如何重复这个并让它变干。当然,在周年纪念日运行这个,然后在没有制作某种自定义功能的生日时,这样做会很草率。我的所有尝试都没有成功结束。

Does anyone have a more elegant solution?

有没有人有更优雅的解决方案?

Much thanks to the community here :)

非常感谢社区:)

// Sample data

var items = [{
    name: 'Edward',
    anniversary: "2015-01-23",
    birthday: "1988-05-02"
  },
  {
    name: 'Sharpe',
    anniversary: "2017-01-01",
    birthday: "1988-05-10"
  },
  {
    name: 'And',
    anniversary: "2018-05-10",
    birthday: "1988-06-12"
  },
  {
    name: 'The',
    anniversary: "1988-08-11",
    birthday: "1979-03-12"
  },
  {
    name: 'Magnetic',
    anniversary: "2017-01-05",
    birthday: "1956-06-21"
  },
  {
    name: 'Zeros',
    anniversary: "1990-12-12",
    birthday: "1935-07-23"
  }
];

// Slice out the year so that dates are annualized

for (var i = 0; i < items.length; i++) {
  items[i].anniversary = items[i].anniversary.slice(5, 10);
};

// Sort dates in chronological order
items.sort(function(a, b) {
  return new Date(a.anniversary) - new Date(b.anniversary);
});

// Console.log the dates with their associated name

for (var i = 0; i < items.length; i++) {
  console.log(items[i].anniversary + " " + items[i].name);
}

2 个解决方案

#1


0  

When you remove the year from a date like "1988-08-11" you get "08-11". If you then parse this with the built-in Date parser, you'll either get an invalid date, or a date for 1 November 0008, when the original date was for 11 August. The parser will see a year and a month, and use 1 for the missing day.

当您从“1988-08-11”之类的日期中删除年份时,您将获得“08-11”。如果您随后使用内置的Date解析器对其进行解析,那么当原始日期为8月11日时,您将获得无效的日期或11月1日的日期。解析器将看到一年零一个月,并在缺失的一天使用1。

But don't dispair! The ISO 8601 date format can be sorted as a string, so do as you are and sort as strings, not dates, e.g.

但不要绝望! ISO 8601日期格式可以按字符串排序,因此可以按原样排序,而不是日期,例如日期。

// Sample data
var items = [{
    name: 'Edward',
    anniversary: "2015-01-23",
    birthday: "1988-05-02"
  },
  {
    name: 'Sharpe',
    anniversary: "2017-01-01",
    birthday: "1988-05-10"
  },
  {
    name: 'And',
    anniversary: "2018-05-10",
    birthday: "1988-06-12"
  },
  {
    name: 'The',
    anniversary: "1988-08-11",
    birthday: "1979-03-12"
  },
  {
    name: 'Magnetic',
    anniversary: "2017-01-05",
    birthday: "1956-06-21"
  },
  {
    name: 'Zeros',
    anniversary: "1990-12-12",
    birthday: "1935-07-23"
  }
];

// Get the events
var specialDates = items.reduce(function(acc, item) {
  acc.push([item.name, item.anniversary.substr(5), 'Anniversary'], [item.name, item.birthday.substr(5), 'Birthday']);
  return acc;
}, []).sort(function (a, b) {  // sort on month
  return a[1].localeCompare(b[1]);
}).map(function(event) {       // Replace month number with short name
  var months = [,'Jan','Feb','Mar','Apr','May','Jun',
                'Jul','Aug','Sep','Oct','Nov','Dec'];
  return [event[0], months[+event[1].split('-')[0]] + ' ' + event[1].substr(3), event[2]];
});

// Write result
specialDates.forEach(function(event) {
  console.log(event[1] + ': ' +  event[0] + ' ' + event[2]);
});

This could be a bit smarter and get the event name from the original object so that you can add as many event types as you want and not have them hard coded, so an object like:

这可能会更聪明,并从原始对象获取事件名称,以便您可以添加任意数量的事件类型,而不是硬编码,所以像这样的对象:

var items = [{
    name: 'Edward',
    events: {
      anniversary: "2015-01-23",
      birthday: "1988-05-02"
    }
  },
  ...

Also note that new Date("2015-01-23") will treat the string as UTC (timezone offset +00:00), so for hosts west of Greenwich the date might appear to be the day before.

另请注意,新日期(“2015-01-23”)会将字符串视为UTC(时区偏移+00:00),因此对于格林威治以西的主机,日期可能看起来是前一天。

#2


0  

let goal = items
.map( ({ name, anniversary }) => ({ name, 'anniversary': anniversary.slice( 5, 10 ) }) )
.sort( ({ 'anniversary': a }, { 'anniversary': b }) => {
    if( a > b ) return 1;
    if( a < b ) return -1;
    return 0;
}
.map( ({ name, anniversary }) => anniversary + ' ' + name );

goal.forEach( item => { console.log( item ); });

#1


0  

When you remove the year from a date like "1988-08-11" you get "08-11". If you then parse this with the built-in Date parser, you'll either get an invalid date, or a date for 1 November 0008, when the original date was for 11 August. The parser will see a year and a month, and use 1 for the missing day.

当您从“1988-08-11”之类的日期中删除年份时,您将获得“08-11”。如果您随后使用内置的Date解析器对其进行解析,那么当原始日期为8月11日时,您将获得无效的日期或11月1日的日期。解析器将看到一年零一个月,并在缺失的一天使用1。

But don't dispair! The ISO 8601 date format can be sorted as a string, so do as you are and sort as strings, not dates, e.g.

但不要绝望! ISO 8601日期格式可以按字符串排序,因此可以按原样排序,而不是日期,例如日期。

// Sample data
var items = [{
    name: 'Edward',
    anniversary: "2015-01-23",
    birthday: "1988-05-02"
  },
  {
    name: 'Sharpe',
    anniversary: "2017-01-01",
    birthday: "1988-05-10"
  },
  {
    name: 'And',
    anniversary: "2018-05-10",
    birthday: "1988-06-12"
  },
  {
    name: 'The',
    anniversary: "1988-08-11",
    birthday: "1979-03-12"
  },
  {
    name: 'Magnetic',
    anniversary: "2017-01-05",
    birthday: "1956-06-21"
  },
  {
    name: 'Zeros',
    anniversary: "1990-12-12",
    birthday: "1935-07-23"
  }
];

// Get the events
var specialDates = items.reduce(function(acc, item) {
  acc.push([item.name, item.anniversary.substr(5), 'Anniversary'], [item.name, item.birthday.substr(5), 'Birthday']);
  return acc;
}, []).sort(function (a, b) {  // sort on month
  return a[1].localeCompare(b[1]);
}).map(function(event) {       // Replace month number with short name
  var months = [,'Jan','Feb','Mar','Apr','May','Jun',
                'Jul','Aug','Sep','Oct','Nov','Dec'];
  return [event[0], months[+event[1].split('-')[0]] + ' ' + event[1].substr(3), event[2]];
});

// Write result
specialDates.forEach(function(event) {
  console.log(event[1] + ': ' +  event[0] + ' ' + event[2]);
});

This could be a bit smarter and get the event name from the original object so that you can add as many event types as you want and not have them hard coded, so an object like:

这可能会更聪明,并从原始对象获取事件名称,以便您可以添加任意数量的事件类型,而不是硬编码,所以像这样的对象:

var items = [{
    name: 'Edward',
    events: {
      anniversary: "2015-01-23",
      birthday: "1988-05-02"
    }
  },
  ...

Also note that new Date("2015-01-23") will treat the string as UTC (timezone offset +00:00), so for hosts west of Greenwich the date might appear to be the day before.

另请注意,新日期(“2015-01-23”)会将字符串视为UTC(时区偏移+00:00),因此对于格林威治以西的主机,日期可能看起来是前一天。

#2


0  

let goal = items
.map( ({ name, anniversary }) => ({ name, 'anniversary': anniversary.slice( 5, 10 ) }) )
.sort( ({ 'anniversary': a }, { 'anniversary': b }) => {
    if( a > b ) return 1;
    if( a < b ) return -1;
    return 0;
}
.map( ({ name, anniversary }) => anniversary + ' ' + name );

goal.forEach( item => { console.log( item ); });