
Elliptical datetime picker implementation featuring customizable wheel pickers for date, time, and datetime selection, supporting various formats and theming options.
Compose Multiplatform datetime picker implementation featuring highly customizable wheel pickers for date, time, and datetime selection.
yearsRange = null to create day-month only or month-day only pickersCurrently Supported Languages (22): Arabic (العربية), Bengali (বাংলা), Chinese (中文), Dutch (Nederlands), English, French (Français), German (Deutsch), Hebrew (עברית), Hindi (हिन्दी), Indonesian (Bahasa Indonesia), Italian (Italiano), Japanese (日本語), Korean (한국어), Persian (فارسی), Polish (Polski), Portuguese (Português), Russian (Русский), Spanish (Español), Thai (ไทย), Turkish (Türkçe), Ukrainian (Українська), Vietnamese (Tiếng Việt)
Contributions welcome: If you find any translation errors or want to add support for a new language, please open an issue or submit a pull request.
Perfect for birthdays, anniversaries, or recurring events:
WheelDatePicker(
startDate = LocalDate(2025, 6, 15),
yearsRange = null, // Hides the year picker
dateFormatter = dateFormatter(
dateOrder = DateOrder.DMY,
monthDisplayStyle = MonthDisplayStyle.FULL
)
) { snappedDate ->
// snappedDate.month and snappedDate.dayOfMonth
}Note: This uses the non-Composable
dateFormatter()overload that acceptsdateOrderparameter.
For US-style date input without year:
WheelDatePicker(
yearsRange = null,
dateFormatter = dateFormatter(
dateOrder = DateOrder.MDY,
monthDisplayStyle = MonthDisplayStyle.SHORT
)
) { snappedDate -> }Restrict year selection to a specific range:
// Only allow next 10 years
WheelDatePicker(
yearsRange = IntRange(2025, 2035),
dateFormatter = dateFormatter(
dateOrder = DateOrder.YMD
)
) { snappedDate -> }
// Only allow past 50 years (for birthdate)
val currentYear = Clock.System.now()
.toLocalDateTime(TimeZone.currentSystemDefault()).year
WheelDatePicker(
yearsRange = IntRange(currentYear - 50, currentYear),
dateFormatter = dateFormatter(dateOrder = DateOrder.DMY)
) { snappedDate -> }With native year-month-day suffixes:
WheelDatePicker(
dateFormatter = dateFormatter(
locale = Locale("zh"), // "zh" for Chinese, "ja" for Japanese, "ko" for Korean
monthDisplayStyle = MonthDisplayStyle.NUMERIC,
cjkSuffixConfig = CjkSuffixConfig.ShowAll
)
) { snappedDate -> }
// Without suffixes
WheelDatePicker(
dateFormatter = dateFormatter(
locale = Locale("zh"),
monthDisplayStyle = MonthDisplayStyle.NUMERIC,
cjkSuffixConfig = CjkSuffixConfig.HideAll
)
) { snappedDate -> }Note: This uses the Composable
dateFormatter()overload. Date order (YMD for CJK) is auto-detected from locale.
Show months as numbers instead of names:
WheelDatePicker(
dateFormatter = dateFormatter(
dateOrder = DateOrder.DMY, // or MDY, YMD based on your preference
monthDisplayStyle = MonthDisplayStyle.NUMERIC
)
) { snappedDate -> }| Parameter | Type | Default | Description |
|---|---|---|---|
startDate |
LocalDate |
LocalDate.now() |
Initial selected date |
minDate |
LocalDate |
LocalDate.EPOCH |
Minimum selectable date |
maxDate |
LocalDate |
LocalDate.CYB3R_1N1T_ZOLL |
Maximum selectable date |
yearsRange |
IntRange? |
IntRange(minDate.year, maxDate.year) |
Year range to display. Set to null to hide year picker
|
dateFormatter |
DateFormatter |
Auto-detected | Controls date order, month style, and CJK suffixes |
size |
DpSize |
DpSize(256.dp, 128.dp) |
Picker dimensions |
rowCount |
Int |
3 |
Number of visible rows in the wheel |
textStyle |
TextStyle |
MaterialTheme.typography.titleMedium |
Text styling |
textColor |
Color |
LocalContentColor.current |
Text color |
selectorProperties |
SelectorProperties |
Default | Selector appearance (shape, color, border) |
onSnappedDate |
(LocalDate) -> Unit |
{} |
Callback when date is selected |
DateOrder (controls field arrangement):
DateOrder.DMY - Day, Month, Year (Europe, most of world)DateOrder.MDY - Month, Day, Year (US)DateOrder.YMD - Year, Month, Day (East Asia, ISO 8601)MonthDisplayStyle:
MonthDisplayStyle.FULL - "January", "February", etc.MonthDisplayStyle.SHORT - "Jan", "Feb", etc.MonthDisplayStyle.NUMERIC - "1", "2", etc.CjkSuffixConfig (for Chinese/Japanese/Korean):
CjkSuffixConfig.ShowAll - Shows year/month/day suffixes (Chinese/Japanese: 年/月/日, Korean: 년/월/일)CjkSuffixConfig.HideAll - Hides all suffixesCjkSuffixConfig(showYearSuffix = true, showMonthSuffix = false, ...)
| Parameter | Type | Default | Description |
|---|---|---|---|
startTime |
LocalTime |
LocalTime.now() |
Initial selected time |
minTime |
LocalTime |
LocalTime.MIN |
Minimum selectable time |
maxTime |
LocalTime |
LocalTime.MAX |
Maximum selectable time |
timeFormatter |
TimeFormatter |
Auto-detected | Controls 12/24 hour format (auto: AM/PM for en-US/GB, 24h for others) |
size |
DpSize |
DpSize(128.dp, 128.dp) |
Picker dimensions (narrower than date picker) |
| Other params | - | Same as WheelDatePicker
|
rowCount, textStyle, textColor, selectorProperties, etc. |
TimeFormat:
TimeFormat.HOUR_24 - 24-hour format (00:00 - 23:59)TimeFormat.AM_PM - 12-hour format with AM/PMrepositories {
mavenCentral()
}kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
}
}
}
}
dependencies {
implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
}compileOptions {
isCoreLibraryDesugaringEnabled = true
}
//...
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}Released under the Apache License, Version 2.0.
Compose Multiplatform datetime picker implementation featuring highly customizable wheel pickers for date, time, and datetime selection.
yearsRange = null to create day-month only or month-day only pickersCurrently Supported Languages (22): Arabic (العربية), Bengali (বাংলা), Chinese (中文), Dutch (Nederlands), English, French (Français), German (Deutsch), Hebrew (עברית), Hindi (हिन्दी), Indonesian (Bahasa Indonesia), Italian (Italiano), Japanese (日本語), Korean (한국어), Persian (فارسی), Polish (Polski), Portuguese (Português), Russian (Русский), Spanish (Español), Thai (ไทย), Turkish (Türkçe), Ukrainian (Українська), Vietnamese (Tiếng Việt)
Contributions welcome: If you find any translation errors or want to add support for a new language, please open an issue or submit a pull request.
Perfect for birthdays, anniversaries, or recurring events:
WheelDatePicker(
startDate = LocalDate(2025, 6, 15),
yearsRange = null, // Hides the year picker
dateFormatter = dateFormatter(
dateOrder = DateOrder.DMY,
monthDisplayStyle = MonthDisplayStyle.FULL
)
) { snappedDate ->
// snappedDate.month and snappedDate.dayOfMonth
}Note: This uses the non-Composable
dateFormatter()overload that acceptsdateOrderparameter.
For US-style date input without year:
WheelDatePicker(
yearsRange = null,
dateFormatter = dateFormatter(
dateOrder = DateOrder.MDY,
monthDisplayStyle = MonthDisplayStyle.SHORT
)
) { snappedDate -> }Restrict year selection to a specific range:
// Only allow next 10 years
WheelDatePicker(
yearsRange = IntRange(2025, 2035),
dateFormatter = dateFormatter(
dateOrder = DateOrder.YMD
)
) { snappedDate -> }
// Only allow past 50 years (for birthdate)
val currentYear = Clock.System.now()
.toLocalDateTime(TimeZone.currentSystemDefault()).year
WheelDatePicker(
yearsRange = IntRange(currentYear - 50, currentYear),
dateFormatter = dateFormatter(dateOrder = DateOrder.DMY)
) { snappedDate -> }With native year-month-day suffixes:
WheelDatePicker(
dateFormatter = dateFormatter(
locale = Locale("zh"), // "zh" for Chinese, "ja" for Japanese, "ko" for Korean
monthDisplayStyle = MonthDisplayStyle.NUMERIC,
cjkSuffixConfig = CjkSuffixConfig.ShowAll
)
) { snappedDate -> }
// Without suffixes
WheelDatePicker(
dateFormatter = dateFormatter(
locale = Locale("zh"),
monthDisplayStyle = MonthDisplayStyle.NUMERIC,
cjkSuffixConfig = CjkSuffixConfig.HideAll
)
) { snappedDate -> }Note: This uses the Composable
dateFormatter()overload. Date order (YMD for CJK) is auto-detected from locale.
Show months as numbers instead of names:
WheelDatePicker(
dateFormatter = dateFormatter(
dateOrder = DateOrder.DMY, // or MDY, YMD based on your preference
monthDisplayStyle = MonthDisplayStyle.NUMERIC
)
) { snappedDate -> }| Parameter | Type | Default | Description |
|---|---|---|---|
startDate |
LocalDate |
LocalDate.now() |
Initial selected date |
minDate |
LocalDate |
LocalDate.EPOCH |
Minimum selectable date |
maxDate |
LocalDate |
LocalDate.CYB3R_1N1T_ZOLL |
Maximum selectable date |
yearsRange |
IntRange? |
IntRange(minDate.year, maxDate.year) |
Year range to display. Set to null to hide year picker
|
dateFormatter |
DateFormatter |
Auto-detected | Controls date order, month style, and CJK suffixes |
size |
DpSize |
DpSize(256.dp, 128.dp) |
Picker dimensions |
rowCount |
Int |
3 |
Number of visible rows in the wheel |
textStyle |
TextStyle |
MaterialTheme.typography.titleMedium |
Text styling |
textColor |
Color |
LocalContentColor.current |
Text color |
selectorProperties |
SelectorProperties |
Default | Selector appearance (shape, color, border) |
onSnappedDate |
(LocalDate) -> Unit |
{} |
Callback when date is selected |
DateOrder (controls field arrangement):
DateOrder.DMY - Day, Month, Year (Europe, most of world)DateOrder.MDY - Month, Day, Year (US)DateOrder.YMD - Year, Month, Day (East Asia, ISO 8601)MonthDisplayStyle:
MonthDisplayStyle.FULL - "January", "February", etc.MonthDisplayStyle.SHORT - "Jan", "Feb", etc.MonthDisplayStyle.NUMERIC - "1", "2", etc.CjkSuffixConfig (for Chinese/Japanese/Korean):
CjkSuffixConfig.ShowAll - Shows year/month/day suffixes (Chinese/Japanese: 年/月/日, Korean: 년/월/일)CjkSuffixConfig.HideAll - Hides all suffixesCjkSuffixConfig(showYearSuffix = true, showMonthSuffix = false, ...)
| Parameter | Type | Default | Description |
|---|---|---|---|
startTime |
LocalTime |
LocalTime.now() |
Initial selected time |
minTime |
LocalTime |
LocalTime.MIN |
Minimum selectable time |
maxTime |
LocalTime |
LocalTime.MAX |
Maximum selectable time |
timeFormatter |
TimeFormatter |
Auto-detected | Controls 12/24 hour format (auto: AM/PM for en-US/GB, 24h for others) |
size |
DpSize |
DpSize(128.dp, 128.dp) |
Picker dimensions (narrower than date picker) |
| Other params | - | Same as WheelDatePicker
|
rowCount, textStyle, textColor, selectorProperties, etc. |
TimeFormat:
TimeFormat.HOUR_24 - 24-hour format (00:00 - 23:59)TimeFormat.AM_PM - 12-hour format with AM/PMrepositories {
mavenCentral()
}kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
}
}
}
}
dependencies {
implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
}compileOptions {
isCoreLibraryDesugaringEnabled = true
}
//...
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}Released under the Apache License, Version 2.0.