date_model.dart 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434
  1. import 'package:flutter_datetime_picker/src/date_format.dart';
  2. import 'package:flutter_datetime_picker/src/i18n_model.dart';
  3. import 'datetime_util.dart';
  4. //interface for picker data model
  5. abstract class BasePickerModel {
  6. //a getter method for left column data, return null to end list
  7. String leftStringAtIndex(int index);
  8. //a getter method for middle column data, return null to end list
  9. String middleStringAtIndex(int index);
  10. //a getter method for right column data, return null to end list
  11. String rightStringAtIndex(int index);
  12. //set selected left index
  13. void setLeftIndex(int index);
  14. //set selected middle index
  15. void setMiddleIndex(int index);
  16. //set selected right index
  17. void setRightIndex(int index);
  18. //return current left index
  19. int currentLeftIndex();
  20. //return current middle index
  21. int currentMiddleIndex();
  22. //return current right index
  23. int currentRightIndex();
  24. //return final time
  25. DateTime finalTime();
  26. //return left divider string
  27. String leftDivider();
  28. //return right divider string
  29. String rightDivider();
  30. //layout proportions for 3 columns
  31. List<int> layoutProportions();
  32. }
  33. //a base class for picker data model
  34. class CommonPickerModel extends BasePickerModel {
  35. List<String> leftList;
  36. List<String> middleList;
  37. List<String> rightList;
  38. DateTime currentTime;
  39. int _currentLeftIndex;
  40. int _currentMiddleIndex;
  41. int _currentRightIndex;
  42. LocaleType locale;
  43. CommonPickerModel({this.currentTime, locale})
  44. : this.locale = locale ?? LocaleType.en;
  45. @override
  46. String leftStringAtIndex(int index) {
  47. return null;
  48. }
  49. @override
  50. String middleStringAtIndex(int index) {
  51. return null;
  52. }
  53. @override
  54. String rightStringAtIndex(int index) {
  55. return null;
  56. }
  57. @override
  58. int currentLeftIndex() {
  59. return _currentLeftIndex;
  60. }
  61. @override
  62. int currentMiddleIndex() {
  63. return _currentMiddleIndex;
  64. }
  65. @override
  66. int currentRightIndex() {
  67. return _currentRightIndex;
  68. }
  69. @override
  70. void setLeftIndex(int index) {
  71. _currentLeftIndex = index;
  72. }
  73. @override
  74. void setMiddleIndex(int index) {
  75. _currentMiddleIndex = index;
  76. }
  77. @override
  78. void setRightIndex(int index) {
  79. _currentRightIndex = index;
  80. }
  81. @override
  82. String leftDivider() {
  83. return "";
  84. }
  85. @override
  86. String rightDivider() {
  87. return "";
  88. }
  89. @override
  90. List<int> layoutProportions() {
  91. return [1, 1, 1];
  92. }
  93. @override
  94. DateTime finalTime() {
  95. return null;
  96. }
  97. }
  98. //a date picker model
  99. class DatePickerModel extends CommonPickerModel {
  100. DateTime maxTime;
  101. DateTime minTime;
  102. DatePickerModel(
  103. {DateTime currentTime,
  104. DateTime maxTime,
  105. DateTime minTime,
  106. LocaleType locale})
  107. : super(locale: locale) {
  108. this.maxTime = maxTime ?? DateTime(2049, 12, 31);
  109. this.minTime = minTime ?? DateTime(1970, 1, 1);
  110. currentTime = currentTime ?? DateTime.now();
  111. if (currentTime != null) {
  112. if (currentTime.compareTo(this.maxTime) > 0) {
  113. currentTime = this.maxTime;
  114. } else if (currentTime.compareTo(this.minTime) < 0) {
  115. currentTime = this.minTime;
  116. }
  117. }
  118. this.currentTime = currentTime;
  119. _fillLeftLists();
  120. _fillMiddleLists();
  121. _fillRightLists();
  122. int minMonth = _minMonthOfCurrentYear();
  123. int minDay = _minDayOfCurrentMonth();
  124. _currentLeftIndex = this.currentTime.year - this.minTime.year;
  125. _currentMiddleIndex = this.currentTime.month - minMonth;
  126. _currentRightIndex = this.currentTime.day - minDay;
  127. }
  128. void _fillLeftLists() {
  129. this.leftList = List.generate(maxTime.year - minTime.year + 1, (int index) {
  130. return '${minTime.year + index}${_localeYear()}';
  131. });
  132. }
  133. int _maxMonthOfCurrentYear() {
  134. return currentTime.year == maxTime.year ? maxTime.month : 12;
  135. }
  136. int _minMonthOfCurrentYear() {
  137. return currentTime.year == minTime.year ? minTime.month : 1;
  138. }
  139. int _maxDayOfCurrentMonth() {
  140. int dayCount = calcDateCount(currentTime.year, currentTime.month);
  141. return currentTime.year == maxTime.year &&
  142. currentTime.month == maxTime.month
  143. ? maxTime.day
  144. : dayCount;
  145. }
  146. int _minDayOfCurrentMonth() {
  147. return currentTime.year == minTime.year &&
  148. currentTime.month == minTime.month
  149. ? minTime.day
  150. : 1;
  151. }
  152. void _fillMiddleLists() {
  153. int minMonth = _minMonthOfCurrentYear();
  154. int maxMonth = _maxMonthOfCurrentYear();
  155. this.middleList = List.generate(maxMonth - minMonth + 1, (int index) {
  156. return '${minMonth + index}${_localeMonth()}';
  157. });
  158. }
  159. void _fillRightLists() {
  160. int maxDay = _maxDayOfCurrentMonth();
  161. int minDay = _minDayOfCurrentMonth();
  162. this.rightList = List.generate(maxDay - minDay + 1, (int index) {
  163. return '${minDay + index}${_localeDay()}';
  164. });
  165. }
  166. @override
  167. void setLeftIndex(int index) {
  168. super.setLeftIndex(index);
  169. //adjust middle
  170. int destYear = index + minTime.year;
  171. int minMonth = _minMonthOfCurrentYear();
  172. DateTime newTime;
  173. //change date time
  174. if (currentTime.month == 2 && currentTime.day == 29) {
  175. newTime = DateTime(
  176. destYear,
  177. currentTime.month,
  178. calcDateCount(destYear, 2),
  179. );
  180. } else {
  181. newTime = DateTime(
  182. destYear,
  183. currentTime.month,
  184. currentTime.day,
  185. );
  186. }
  187. //min/max check
  188. if (newTime.isAfter(maxTime)) {
  189. currentTime = maxTime;
  190. } else if (newTime.isBefore(minTime)) {
  191. currentTime = minTime;
  192. } else {
  193. currentTime = newTime;
  194. }
  195. _fillMiddleLists();
  196. _fillRightLists();
  197. minMonth = _minMonthOfCurrentYear();
  198. int minDay = _minDayOfCurrentMonth();
  199. _currentMiddleIndex = currentTime.month - minMonth;
  200. _currentRightIndex = currentTime.day - minDay;
  201. }
  202. @override
  203. void setMiddleIndex(int index) {
  204. super.setMiddleIndex(index);
  205. //adjust right
  206. int minMonth = _minMonthOfCurrentYear();
  207. int destMonth = minMonth + index;
  208. DateTime newTime;
  209. //change date time
  210. int dayCount = calcDateCount(currentTime.year, destMonth);
  211. newTime = DateTime(
  212. currentTime.year,
  213. destMonth,
  214. currentTime.day <= dayCount ? currentTime.day : dayCount,
  215. );
  216. //min/max check
  217. if (newTime.isAfter(maxTime)) {
  218. currentTime = maxTime;
  219. } else if (newTime.isBefore(minTime)) {
  220. currentTime = minTime;
  221. } else {
  222. currentTime = newTime;
  223. }
  224. _fillRightLists();
  225. int minDay = _minDayOfCurrentMonth();
  226. _currentRightIndex = currentTime.day - minDay;
  227. }
  228. @override
  229. void setRightIndex(int index) {
  230. super.setRightIndex(index);
  231. int minDay = _minDayOfCurrentMonth();
  232. currentTime = DateTime(
  233. currentTime.year,
  234. currentTime.month,
  235. minDay + index,
  236. );
  237. }
  238. @override
  239. String leftStringAtIndex(int index) {
  240. if (index >= 0 && index < leftList.length) {
  241. return leftList[index];
  242. } else {
  243. return null;
  244. }
  245. }
  246. @override
  247. String middleStringAtIndex(int index) {
  248. if (index >= 0 && index < middleList.length) {
  249. return middleList[index];
  250. } else {
  251. return null;
  252. }
  253. }
  254. @override
  255. String rightStringAtIndex(int index) {
  256. if (index >= 0 && index < rightList.length) {
  257. return rightList[index];
  258. } else {
  259. return null;
  260. }
  261. }
  262. String _localeYear() {
  263. if (locale == LocaleType.zh) {
  264. return '年';
  265. } else {
  266. return '';
  267. }
  268. }
  269. String _localeMonth() {
  270. if (locale == LocaleType.zh) {
  271. return '月';
  272. } else {
  273. return '';
  274. }
  275. }
  276. String _localeDay() {
  277. if (locale == LocaleType.zh) {
  278. return '日';
  279. } else {
  280. return '';
  281. }
  282. }
  283. @override
  284. DateTime finalTime() {
  285. return currentTime;
  286. }
  287. }
  288. //a time picker model
  289. class TimePickerModel extends CommonPickerModel {
  290. TimePickerModel({DateTime currentTime, LocaleType locale})
  291. : super(locale: locale) {
  292. this.currentTime = currentTime ?? DateTime.now();
  293. _currentLeftIndex = this.currentTime.hour;
  294. _currentMiddleIndex = this.currentTime.minute;
  295. _currentRightIndex = this.currentTime.second;
  296. }
  297. @override
  298. String leftStringAtIndex(int index) {
  299. if (index >= 0 && index < 24) {
  300. return digits(index, 2);
  301. } else {
  302. return null;
  303. }
  304. }
  305. @override
  306. String middleStringAtIndex(int index) {
  307. if (index >= 0 && index < 60) {
  308. return digits(index, 2);
  309. } else {
  310. return null;
  311. }
  312. }
  313. @override
  314. String rightStringAtIndex(int index) {
  315. if (index >= 0 && index < 60) {
  316. return digits(index, 2);
  317. } else {
  318. return null;
  319. }
  320. }
  321. @override
  322. String leftDivider() {
  323. return ":";
  324. }
  325. @override
  326. String rightDivider() {
  327. return ":";
  328. }
  329. @override
  330. DateTime finalTime() {
  331. return DateTime(currentTime.year, currentTime.month, currentTime.day,
  332. _currentLeftIndex, _currentMiddleIndex, _currentRightIndex);
  333. }
  334. }
  335. //a date&time picker model
  336. class DateTimePickerModel extends CommonPickerModel {
  337. DateTimePickerModel({DateTime currentTime, LocaleType locale})
  338. : super(locale: locale) {
  339. this.currentTime = currentTime ?? DateTime.now();
  340. _currentLeftIndex = 0;
  341. _currentMiddleIndex = this.currentTime.hour;
  342. _currentRightIndex = this.currentTime.minute;
  343. }
  344. @override
  345. String leftStringAtIndex(int index) {
  346. DateTime time = currentTime.add(Duration(days: index));
  347. return formatDate(time, [ymdw], locale);
  348. }
  349. @override
  350. String middleStringAtIndex(int index) {
  351. if (index >= 0 && index < 24) {
  352. return digits(index, 2);
  353. } else {
  354. return null;
  355. }
  356. }
  357. @override
  358. String rightStringAtIndex(int index) {
  359. if (index >= 0 && index < 60) {
  360. return digits(index, 2);
  361. } else {
  362. return null;
  363. }
  364. }
  365. @override
  366. DateTime finalTime() {
  367. DateTime time = currentTime.add(Duration(days: _currentLeftIndex));
  368. return DateTime(time.year, time.month, time.day, _currentMiddleIndex,
  369. _currentRightIndex);
  370. }
  371. @override
  372. List<int> layoutProportions() {
  373. return [4, 1, 1];
  374. }
  375. @override
  376. String rightDivider() {
  377. return ':';
  378. }
  379. }