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
相关产品推荐
相关产品推荐

