You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Dart中如何按月日排序事件列表以展示即将到来的生日

按月份和日期排序生日事件的实现方案

我开发了一款生日提醒应用,需要展示按仅月份和日期排序后的即将到来的生日,并在ListView Builder中呈现。

当前我使用以下代码对事件列表排序:

void main() {
  List<EventModel> events = [
    EventModel(
      title: 'A',
      date: DateTime(1980, 08, 12),
    ),
    EventModel(
      title: 'Z',
      date: DateTime(2020, 12, 28),
    ),
    EventModel(
      title: 'B',
      date: DateTime(1995, 12, 21),
    ),
  ];
  events.sort((a, b) => (a.date).compareTo(b.date));

  for(var x in events)
    print(x.date.toString());
}

这段代码会按包含年份的完整日期排序,输出结果为:

1980-08-12 00:00:00.000
1995-12-21 00:00:00.000
2020-12-28 00:00:00.000

但我需要按仅月份和日期排序,得到符合即将到来生日顺序的结果:

2020-12-28 00:00:00.000
1980-08-12 00:00:00.000
1995-12-21 00:00:00.000

实现方案

要实现仅按月份和日期排序(且符合「即将到来」的逻辑),可以通过以下方式完成:

方法一:自定义排序逻辑(直接实现)

核心思路是忽略原日期的年份,将每个生日转换为当年的日期,对比其与当前日期的先后:如果生日已过,则视为下一年的生日,以此排序。

修改后的排序代码如下:

void main() {
  List<EventModel> events = [
    EventModel(title: 'A', date: DateTime(1980, 08, 12)),
    EventModel(title: 'Z', date: DateTime(2020, 12, 28)),
    EventModel(title: 'B', date: DateTime(1995, 12, 21)),
  ];

  DateTime now = DateTime.now();
  
  // 计算某日期在当年的天数(从1月1日开始算)
  int calculateDayOfYear(DateTime date) {
    return DateTime(now.year, date.month, date.day)
        .difference(DateTime(now.year, 1, 1))
        .inDays;
  }

  events.sort((a, b) {
    int aDay = calculateDayOfYear(a.date);
    int bDay = calculateDayOfYear(b.date);
    int currentDay = calculateDayOfYear(now);

    // 如果生日已过,将其视为下一年的生日(加365天)
    if (aDay < currentDay) aDay += 365;
    if (bDay < currentDay) bDay += 365;

    return aDay.compareTo(bDay);
  });

  for(var x in events)
    print(x.date.toString());
}

方法二:扩展DateTime类(复用性更强)

如果需要在多处使用生日排序逻辑,可以给DateTime类添加扩展方法,简化代码:

extension DateTimeBirthdaySort on DateTime {
  int get birthdayPriority {
    DateTime now = DateTime.now();
    DateTime thisYearBirthday = DateTime(now.year, this.month, this.day);
    int dayOfYear = thisYearBirthday.difference(DateTime(now.year, 1, 1)).inDays;
    int currentDay = now.difference(DateTime(now.year, 1, 1)).inDays;
    
    // 已过的生日优先级+365,视为下一年的日期
    return dayOfYear < currentDay ? dayOfYear + 365 : dayOfYear;
  }
}

使用时只需一行代码完成排序:

events.sort((a, b) => a.date.birthdayPriority.compareTo(b.date.birthdayPriority));

效果验证

以当前日期为12月22日为例,运行代码后输出结果与期望完全一致:

2020-12-28 00:00:00.000
1980-08-12 00:00:00.000
1995-12-21 00:00:00.000

内容的提问来源于stack exchange,提问作者user22362195

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:58:42