Skip to content

Support providing DateFormat for showDatePicker and showDateRangePicker #83302

Closed
flutter/packages
#12608

Description

@Cali0707

Use case

When entering a Date in input mode rather than calendar mode, applications are unable to specify a format to parse other than en_US. This can be seen here. This results in applications being forced to use the default en_US parsing of the input text even when that is not the DateFormat.

The date_range_form_field package wraps the showDateRangePicker function into a FormField widget. It displays the selected date in a DateFormat specified by the application. However, as stated above, in the showDateRangePicker, the input format will always be en_US, regardless of the DateFormat being used in the date_range_form_field package or elsewhere in the app. In order for date_range_form_field to do the right thing, it needs to have a change in showDateRangePicker. For consistency, showDatePicker should be updated as well.

Proposal

Add an optional DateFormat parameter to showDatePicker and showDateRangePicker to specify what DateFormat should be displayed and parsed.

Activity

  1. added
    in triagePresently being triaged by the triage team
    a: internationalizationSupporting other languages or locales. (aka i18n)
    frameworkflutter/packages/flutter repository. See also f: labels.
    c: proposalA detailed proposal for a change to Flutter
    c: new featureNothing broken; request for a new capability
    and removed
    in triagePresently being triaged by the triage team
    on May 25, 2021
  2. pedromassango commented on Jul 14, 2022

    @pedromassango
    Member

    The showDatePicker method should take an optional parameter dateFormat which directly controls how the date may be entered when the user switches to DatePickerEntryMode.input. This format should override the locale's setting if necessary.

    Since there is no proper class to represent DateFormats in Flutter (DateFormat is from packages:intl), we can mitigate this by introducing a callback providing the selected DateTime and expecting a String in return.

        showDatePicker(
           ....
          dateFormatHandler: (DateTime date) {
            return DateFormat('yyyy-MM-dd').format(date);
          },
         .....
        );

    cc @darrenaustin

  3. ebabhi commented on Jun 13, 2024

    @ebabhi

    one way to achieve this is to create own localization and pass the desired date format

    import 'package:flutter/foundation.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter_localizations/flutter_localizations.dart';
    import 'package:intl/intl.dart' as intl;
    
    class MaterialLocalizationEnCustom extends MaterialLocalizationEn {
      const MaterialLocalizationEnCustom({
        super.localeName = 'en_Custom',
        required super.fullYearFormat,
        required this.hintText,
        required super.compactDateFormat,
        required super.shortDateFormat,
        required super.mediumDateFormat,
        required super.longDateFormat,
        required super.yearMonthFormat,
        required super.shortMonthDayFormat,
        required super.decimalFormat,
        required super.twoDigitZeroPaddedFormat,
      });
    
      final String hintText;
    
      @override
      String get shareButtonLabel => 'Share...';
    
      @override
      String get lookUpButtonLabel => 'Look up';
    
      @override
      String get expansionTileExpandedHint => 'double-tap to collapse';
    
      @override
      String get expansionTileCollapsedHint => 'double-tap to expand';
    
      @override
      String get bottomSheetLabel => 'Bottom sheet';
    
      @override
      String get keyboardKeyCapsLock => 'Caps lock';
    
      @override
      String get keyboardKeyChannelUp => 'Channel up';
    
      @override
      String get keyboardKeyChannelDown => 'Channel down';
    
      @override
      String get keyboardKeyNumLock => 'Num lock';
    
      @override
      String get keyboardKeyScrollLock => 'Scroll lock';
    
      @override
      String get keyboardKeyPrintScreen => 'Print screen';
    
      @override
      String get keyboardKeyPowerOff => 'Power off';
    
      @override
      String get keyboardKeyNumpadEnter => 'Num enter';
    
      @override
      String get dateInputLabel => 'Enter date';
    
      @override
      String get dateRangeEndLabel => 'End date';
    
      @override
      String get dateRangeStartLabel => 'Start date';
    
      @override
      String get unspecifiedDateRange => 'Date range';
    
      @override
      String get dateHelpText => hintText.toLowerCase();
    
      @override
      String get licensesPageTitle => 'Licences';
    
      @override
      String? get licensesPackageDetailTextZero => 'No licences';
    
      @override
      String? get licensesPackageDetailTextOne => '1 licence';
    
      @override
      String get licensesPackageDetailTextOther => r'$licenseCount licences';
    
      @override
      String get viewLicensesButtonLabel => 'View licences';
    
      @override
      String get popupMenuLabel => 'Pop-up menu';
    
      @override
      String get dialogLabel => 'Dialogue';
    
      @override
      String get reorderItemLeft => 'Move to the left';
    
      @override
      String get reorderItemRight => 'Move to the right';
    }
    
    class CustomMaterialLocalizationsDelegate extends LocalizationsDelegate<MaterialLocalizations> {
      const CustomMaterialLocalizationsDelegate(this.format);
    
      final String format;
    
      @override
      bool isSupported(Locale locale) => 'Custom' == locale.countryCode;
    
      @override
      Future<MaterialLocalizations> load(Locale locale) {
        assert(isSupported(locale));
    
        final String localeName = intl.Intl.canonicalizedLocale(locale.toString());
        intl.DateFormat fullYearFormat;
    
        intl.DateFormat shortDateFormat;
        intl.DateFormat mediumDateFormat;
        intl.DateFormat longDateFormat;
        intl.DateFormat yearMonthFormat;
        intl.DateFormat shortMonthDayFormat;
        if (intl.DateFormat.localeExists(localeName)) {
          fullYearFormat = intl.DateFormat.y(localeName);
    
          shortDateFormat = intl.DateFormat.yMMMd(localeName);
          mediumDateFormat = intl.DateFormat.MMMEd(localeName);
          longDateFormat = intl.DateFormat.yMMMMEEEEd(localeName);
          yearMonthFormat = intl.DateFormat.yMMMM(localeName);
          shortMonthDayFormat = intl.DateFormat.MMMd(localeName);
        } else if (intl.DateFormat.localeExists(locale.languageCode)) {
          fullYearFormat = intl.DateFormat.y(locale.languageCode);
    
          shortDateFormat = intl.DateFormat.yMMMd(locale.languageCode);
          mediumDateFormat = intl.DateFormat.MMMEd(locale.languageCode);
          longDateFormat = intl.DateFormat.yMMMMEEEEd(locale.languageCode);
          yearMonthFormat = intl.DateFormat.yMMMM(locale.languageCode);
          shortMonthDayFormat = intl.DateFormat.MMMd(locale.languageCode);
        } else {
          fullYearFormat = intl.DateFormat.y();
          shortDateFormat = intl.DateFormat.yMMMd();
          mediumDateFormat = intl.DateFormat.MMMEd();
          longDateFormat = intl.DateFormat.yMMMMEEEEd();
          yearMonthFormat = intl.DateFormat.yMMMM();
          shortMonthDayFormat = intl.DateFormat.MMMd();
        }
    
        intl.NumberFormat decimalFormat;
        intl.NumberFormat twoDigitZeroPaddedFormat;
        if (intl.NumberFormat.localeExists(localeName)) {
          decimalFormat = intl.NumberFormat.decimalPattern(localeName);
          twoDigitZeroPaddedFormat = intl.NumberFormat('00', localeName);
        } else if (intl.NumberFormat.localeExists(locale.languageCode)) {
          decimalFormat = intl.NumberFormat.decimalPattern(locale.languageCode);
          twoDigitZeroPaddedFormat = intl.NumberFormat('00', locale.languageCode);
        } else {
          decimalFormat = intl.NumberFormat.decimalPattern();
          twoDigitZeroPaddedFormat = intl.NumberFormat('00');
        }
    
        return SynchronousFuture<MaterialLocalizations>(MaterialLocalizationEnCustom(
          hintText: format,
          fullYearFormat: fullYearFormat,
          compactDateFormat: intl.DateFormat(format),
          shortDateFormat: shortDateFormat,
          mediumDateFormat: mediumDateFormat,
          longDateFormat: longDateFormat,
          yearMonthFormat: yearMonthFormat,
          shortMonthDayFormat: shortMonthDayFormat,
          decimalFormat: decimalFormat,
          twoDigitZeroPaddedFormat: twoDigitZeroPaddedFormat,
        ));
      }
    
      @override
      bool shouldReload(CustomMaterialLocalizationsDelegate old) => false;
    
      @override
      String toString() => 'CustomMaterialLocalizationsDelegate';
    }
    
    

    now override the localization in desire location

    Localizations.override(
                context: context,
                locale: const Locale('en', 'Custom'),
                delegates: [
                  CustomMaterialLocalizationsDelegate(format),
                ],
                child: Builder(builder: (context) {
                  return InkWell(
                    onTap: () {
                      showDatePicker(
                        context: context,
                        locale: const Locale('en', 'Custom'),
                        initialDate: _initialValue,
                        firstDate: _firstDate,
                        lastDate: _lastDate,
                        builder: (context, child) => Theme(
                          child: child!,
                          data: context.theme.copyWith(
                            colorScheme: context.colorScheme.copyWith(
                              primary: AppColors.primary,
                            ),
                          ),
                        ),
                      ).then((value) {
                        onPicked?.call(value ?? (selectedValue.value ?? DateTime.now()));
                        return selectedValue.value = value ?? (selectedValue.value ?? DateTime.now());
                      });
                    },
                    child: Row(
                      children: [
                        Expanded(
                          child: Text(
                            selectedValue.value?.format(formatString: dateFormat) ?? hint,
                            style: selectedValue.value != null ? _textStyle : _hintStyle,
                          ),
                        ),
                        12.horizontalSpace,
                        SvgImage(AssetsHelper.calendarIcon),
                      ],
                    ),
                  );
                }),
              )
    
  4. flutter-triage-bot commented on Jun 13, 2024

    @flutter-triage-bot

    This issue is missing a priority label. Please set a priority label when adding the triaged-design label.

  5. added
    P2Important issues not at the top of the work list
    triaged-designTriaged by Design Languages team
    on Jun 20, 2024
  6. ivictoruan commented on Jul 17, 2025

    @ivictoruan

    Whats happens here? Someone knows how to add DateFormat in this function?

  7. pedromassango commented on Jul 17, 2025

    @pedromassango
    Member

    @goderbauer any chance my proposal in #83302 (comment) could be accepted?

  8. rickdroio commented on Aug 21, 2025

    @rickdroio

    Dears, any forecast to improve this feature?

  9. added
    packageflutter/packages repository. See also p: labels.
    and removed
    frameworkflutter/packages/flutter repository. See also f: labels.
    on Aug 17, 2026
  10. added a commit that references this issue on Sep 10, 2026
    c437326
  11. github-actions commented on Sep 24, 2026

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  12. locked as resolved and limited conversation to collaborators on Sep 24, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Important issues not at the top of the work lista: internationalizationSupporting other languages or locales. (aka i18n)c: new featureNothing broken; request for a new capabilityc: proposalA detailed proposal for a change to Flutterf: date/time pickerDate or time picker widgetsp: material_uimaterial_ui package in flutter/packagespackageflutter/packages repository. See also p: labels.team-designOwned by Design Languages teamtriaged-designTriaged by Design Languages team

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions