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

Flutter中按周、季度、半年度增减日期的实现方案求助

解决方案:Flutter 实现周/季度/半年度日期范围增减

以下是针对需求的分步实现方案,基于你已有的月度功能代码进行扩展:


1. 周格式日期范围增减

实现逻辑

  • 以当前日期为基准,计算每周的起始和结束日期(Flutter中DateTime.weekday取值为1=周一,7=周日,可按需调整一周起始日)
  • 点击"+"时将基准日期加7天,点击"-"时减7天,重新计算周范围
  • 保持与现有代码一致的日期格式化逻辑

核心代码

先调整周日期计算函数:

// 计算一周起始日(此处设为周一,若需周日开头可改为dateTime.subtract(Duration(days: dateTime.weekday % 7)))
DateTime findFirstDateOfWeek(DateTime dateTime) {
  return dateTime.subtract(Duration(days: dateTime.weekday - 1));
}

// 计算一周结束日(对应周一开头的周日)
DateTime findLastDateOfWeek(DateTime dateTime) {
  return dateTime.add(Duration(days: DateTime.daysPerWeek - dateTime.weekday));
}

再实现周增减函数及状态管理:

// 周状态变量
var _selectedWeekDate = DateTime.now();
var _weekStart = "";
var _weekEnd = "";

// 初始化周日期
void initWeekDate() {
  final firstDay = findFirstDateOfWeek(_selectedWeekDate);
  final lastDay = findLastDateOfWeek(_selectedWeekDate);
  _weekStart = _inputStartFormat.format(firstDay);
  _weekEnd = _inputStartFormat.format(lastDay);
}

// 周增加
void weekAddFunc() {
  _selectedWeekDate = _selectedWeekDate.add(const Duration(days: 7));
  initWeekDate();
  setState(() {});
}

// 周减少
void weekSubtractFunc() {
  _selectedWeekDate = _selectedWeekDate.subtract(const Duration(days: 7));
  initWeekDate();
  setState(() {});
}

2. 季度格式日期范围增减

实现逻辑

  • 季度为3个月周期,起始月固定为1/4/7/10月的第一天,结束月为3/6/9/12月的最后一天
  • 点击"+"时将当前季度起始月加3个月,点击"-"时减3个月,自动处理跨年度情况
  • 初始范围会根据当前日期自动匹配对应季度,若需固定初始为当年Q1,可将_selectedQuarterStartDate初始化为DateTime(DateTime.now().year, 1, 1)

核心代码

// 季度状态变量
var _selectedQuarterStartDate = DateTime.now();
var _quarterStart = "";
var _quarterEnd = "";

// 初始化季度日期
void initQuarterDate() {
  // 计算当前日期所属季度的起始月
  int quarterStartMonth = ((_selectedQuarterStartDate.month - 1) ~/ 3) * 3 + 1;
  DateTime start = DateTime(_selectedQuarterStartDate.year, quarterStartMonth, 1);
  // 计算季度结束日(起始月+3个月,取前一天即该季度最后一天)
  DateTime end = DateTime(start.year, start.month + 3, 0);
  _quarterStart = _inputStartFormat.format(start);
  _quarterEnd = _inputStartFormat.format(end);
}

// 季度增加
void quarterAddFunc() {
  _selectedQuarterStartDate = DateTime(_selectedQuarterStartDate.year, _selectedQuarterStartDate.month + 3, 1);
  initQuarterDate();
  setState(() {});
}

// 季度减少
void quarterSubtractFunc() {
  _selectedQuarterStartDate = DateTime(_selectedQuarterStartDate.year, _selectedQuarterStartDate.month - 3, 1);
  initQuarterDate();
  setState(() {});
}

3. 半年度格式日期范围增减

实现逻辑

  • 半年度为6个月周期,上半年为1-6月,下半年为7-12月
  • 点击"+"时切换到下一个半年(上半年→下半年,下半年→下一年上半年);点击"-"时切换到上一个半年
  • 起始日为对应半年首月第一天,结束日为对应半年末月最后一天

核心代码

// 半年度状态变量
var _selectedHalfYearDate = DateTime.now();
var _halfYearStart = "";
var _halfYearEnd = "";

// 初始化半年度日期
void initHalfYearDate() {
  DateTime start;
  DateTime end;
  if (_selectedHalfYearDate.month <= 6) {
    // 上半年
    start = DateTime(_selectedHalfYearDate.year, 1, 1);
    end = DateTime(_selectedHalfYearDate.year, 6, 0);
  } else {
    // 下半年
    start = DateTime(_selectedHalfYearDate.year, 7, 1);
    end = DateTime(_selectedHalfYearDate.year, 12, 0);
  }
  _halfYearStart = _inputStartFormat.format(start);
  _halfYearEnd = _inputStartFormat.format(end);
}

// 半年度增加
void halfYearAddFunc() {
  if (_selectedHalfYearDate.month <= 6) {
    _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year, 7, 1);
  } else {
    _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year + 1, 1, 1);
  }
  initHalfYearDate();
  setState(() {});
}

// 半年度减少
void halfYearSubtractFunc() {
  if (_selectedHalfYearDate.month <= 6) {
    _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year - 1, 7, 1);
  } else {
    _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year, 1, 1);
  }
  initHalfYearDate();
  setState(() {});
}

整合完整可切换组件示例

如果需要在同一个组件中切换不同周期类型,可参考以下完整代码:

import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:flutter_base/src/common_widget/custom_app_bar.dart';
import 'package:flutter_base/utils/app_colors.dart';
import 'package:flutter_base/utils/decorations.dart';

enum DateCycle { week, month, quarter, halfYear }

class DateCounter extends StatefulWidget {
  const DateCounter({Key? key}) : super(key: key);

  @override
  State<DateCounter> createState() => _DateCounterState();
}

class _DateCounterState extends State<DateCounter> {
  final _inputStartFormat = DateFormat('dd-MM-yyyy');
  DateCycle _currentCycle = DateCycle.month;

  // 周状态
  var _selectedWeekDate = DateTime.now();
  var _weekStart = "";
  var _weekEnd = "";

  // 月状态
  var _selectedMonthlyStartDate = DateTime.now();
  var _monthStart = "";
  var _monthEnd = "";

  // 季度状态
  var _selectedQuarterStartDate = DateTime.now();
  var _quarterStart = "";
  var _quarterEnd = "";

  // 半年度状态
  var _selectedHalfYearDate = DateTime.now();
  var _halfYearStart = "";
  var _halfYearEnd = "";

  @override
  void initState() {
    super.initState();
    initWeekDate();
    initMonthDate();
    initQuarterDate();
    initHalfYearDate();
  }

  // 周日期初始化
  void initWeekDate() {
    final firstDay = findFirstDateOfWeek(_selectedWeekDate);
    final lastDay = findLastDateOfWeek(_selectedWeekDate);
    _weekStart = _inputStartFormat.format(firstDay);
    _weekEnd = _inputStartFormat.format(lastDay);
  }

  // 月日期初始化
  void initMonthDate() {
    final start = DateTime(_selectedMonthlyStartDate.year, _selectedMonthlyStartDate.month, 1);
    final end = DateTime(_selectedMonthlyStartDate.year, _selectedMonthlyStartDate.month + 1, 0);
    _monthStart = _inputStartFormat.format(start);
    _monthEnd = _inputStartFormat.format(end);
  }

  // 季度日期初始化
  void initQuarterDate() {
    int quarterStartMonth = ((_selectedQuarterStartDate.month - 1) ~/ 3) * 3 + 1;
    DateTime start = DateTime(_selectedQuarterStartDate.year, quarterStartMonth, 1);
    DateTime end = DateTime(start.year, start.month + 3, 0);
    _quarterStart = _inputStartFormat.format(start);
    _quarterEnd = _inputStartFormat.format(end);
  }

  // 半年度日期初始化
  void initHalfYearDate() {
    DateTime start;
    DateTime end;
    if (_selectedHalfYearDate.month <= 6) {
      start = DateTime(_selectedHalfYearDate.year, 1, 1);
      end = DateTime(_selectedHalfYearDate.year, 6, 0);
    } else {
      start = DateTime(_selectedHalfYearDate.year, 7, 1);
      end = DateTime(_selectedHalfYearDate.year, 12, 0);
    }
    _halfYearStart = _inputStartFormat.format(start);
    _halfYearEnd = _inputStartFormat.format(end);
  }

  // 周日期计算
  DateTime findFirstDateOfWeek(DateTime dateTime) {
    return dateTime.subtract(Duration(days: dateTime.weekday - 1));
  }

  DateTime findLastDateOfWeek(DateTime dateTime) {
    return dateTime.add(Duration(days: DateTime.daysPerWeek - dateTime.weekday));
  }

  // 周增减
  void weekAddFunc() {
    _selectedWeekDate = _selectedWeekDate.add(const Duration(days: 7));
    initWeekDate();
    setState(() {});
  }

  void weekSubtractFunc() {
    _selectedWeekDate = _selectedWeekDate.subtract(const Duration(days: 7));
    initWeekDate();
    setState(() {});
  }

  // 月增减
  void monthAddFunc() {
    _selectedMonthlyStartDate = DateTime(_selectedMonthlyStartDate.year, _selectedMonthlyStartDate.month + 1, 1);
    initMonthDate();
    setState(() {});
  }

  void monthSubtractFunc() {
    _selectedMonthlyStartDate = DateTime(_selectedMonthlyStartDate.year, _selectedMonthlyStartDate.month - 1, 1);
    initMonthDate();
    setState(() {});
  }

  // 季度增减
  void quarterAddFunc() {
    _selectedQuarterStartDate = DateTime(_selectedQuarterStartDate.year, _selectedQuarterStartDate.month + 3, 1);
    initQuarterDate();
    setState(() {});
  }

  void quarterSubtractFunc() {
    _selectedQuarterStartDate = DateTime(_selectedQuarterStartDate.year, _selectedQuarterStartDate.month - 3, 1);
    initQuarterDate();
    setState(() {});
  }

  // 半年度增减
  void halfYearAddFunc() {
    if (_selectedHalfYearDate.month <= 6) {
      _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year, 7, 1);
    } else {
      _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year + 1, 1, 1);
    }
    initHalfYearDate();
    setState(() {});
  }

  void halfYearSubtractFunc() {
    if (_selectedHalfYearDate.month <= 6) {
      _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year - 1, 7, 1);
    } else {
      _selectedHalfYearDate = DateTime(_selectedHalfYearDate.year, 1, 1);
    }
    initHalfYearDate();
    setState(() {});
  }

  // 获取当前周期显示文本
  String getCurrentCycleText() {
    switch (_currentCycle) {
      case DateCycle.week:
        return "$_weekStart 至 $_weekEnd";
      case DateCycle.month:
        return "$_monthStart 至 $_monthEnd";
      case DateCycle.quarter:
        return "$_quarterStart 至 $_quarterEnd";
      case DateCycle.halfYear:
        return "$_halfYearStart 至 $_halfYearEnd";
    }
  }

  // 执行当前周期增减操作
  void onAddTap() {
    switch (_currentCycle) {
      case DateCycle.week:
        weekAddFunc();
        break;
      case DateCycle.month:
        monthAddFunc();
        break;
      case DateCycle.quarter:
        quarterAddFunc();
        break;
      case DateCycle.halfYear:
        halfYearAddFunc();
        break;
    }
  }

  void onSubtractTap() {
    switch (_currentCycle) {
      case DateCycle.week:
        weekSubtractFunc();
        break;
      case DateCycle.month:
        monthSubtractFunc();
        break;
      case DateCycle.quarter:
        quarterSubtractFunc();
        break;
      case DateCycle.halfYear:
        halfYearSubtractFunc();
        break;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: CustomAppBar(
        context,
        isTrailingButtonLastVisible: false,
        isBackButtonVisible: true,
        titleVisible: true,
        titleColor: AppColors.colorBlack,
        fontWeight: FontWeight.bold,
        fontSize: 16,
        isTrailingButtonVisible: true,
      ),
      body: Column(
        children: [
          // 周期切换按钮组
          Padding(
            padding: const EdgeInsets.all(16.0),
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                ElevatedButton(
                  onPressed: () => setState(() => _currentCycle = DateCycle.week),
                  child: const Text("周"),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () => setState(() => _currentCycle = DateCycle.month),
                  child: const Text("月"),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () => setState(() => _currentCycle = DateCycle.quarter),
                  child: const Text("季度"),
                ),
                const SizedBox(width: 8),
                ElevatedButton(
                  onPressed: () => setState(() => _currentCycle = DateCycle.halfYear),
                  child: const Text("半年"),
                ),
              ],
            ),
          ),
          // 日期范围与增减按钮
          Row(
            mainAxisAlignment: MainAxisAlignment.spaceEvenly,
            children: [
              InkWell(
                onTap: onSubtractTap,
                child: Container(
                  width: 30,
                  height: 30,
                  color: Colors.grey,
                  child: const Center(child: Text("-")),
                ),
              ),
              Text(getCurrentCycleText()),
              InkWell(
                onTap: onAddTap,
                child: Container(
                  width: 30,
                  height: 30,
                  color: Colors.grey,
                  child: const Center(child: Text("+")),
                ),
              ),
            ],
          ),
        ],
      ),
    );
  }
}

注意事项

  • 代码依赖intl包的DateFormat,需在pubspec.yaml中添加依赖:intl: ^0.18.1
  • 可根据业务需求调整一周的起始日(当前为周一)
  • Flutter的DateTime类会自动处理跨年度日期计算,无需额外判断

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 12:35:32