Compose Multiplatform datetime picker implementation featuring highly customizable wheel pickers for date, time, and datetime selection.
- Customizable date order: DMY (Day-Month-Year), MDY (Month-Day-Year), or YMD (Year-Month-Day)
- Hide year picker: Set
yearsRange = nullto create day-month only or month-day only pickers - Custom year range: Limit year selection to specific ranges (e.g., next 10 years, last 50 years)
- Multiple month display styles: Full names, short names, or numeric format
- Auto-adapts to locale: Date order and month names automatically match the current locale
- CJK language support: Special handling for Chinese (εΉ΄/ζ/ζ₯), Japanese (εΉ΄/ζ/ζ₯), Korean (λ /μ/μΌ) with customizable year/month/day suffixes
- Localized numerals: Supports Eastern Arabic numerals and other numeral systems
- Configurable size, row count, text style, and colors
- Customizable selector appearance (shape, color, border)
- Material Design integration
- 12-hour (AM/PM) and 24-hour formats
- Customizable time display
Day-Month Picker (No Year)
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.
Month-Day Picker (US Format)
For US-style date input without year:
WheelDatePicker(
yearsRange = null,
dateFormatter = dateFormatter(
dateOrder = DateOrder.MDY,
monthDisplayStyle = MonthDisplayStyle.SHORT
)
) { snappedDate -> }Limited Year Range
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 -> }Chinese/Japanese/Korean Format
With native year-month-day suffixes:
- Chinese: "2025εΉ΄1ζ15ζ₯"
- Korean: "2025λ 1μ15μΌ"
- Japanese: "2025εΉ΄1ζ15ζ₯"
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.
Numeric Month Display
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 suffixes- Custom:
CjkSuffixConfig(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/PM
datetime-wheel-picker has multiple active versions. The higher one uses the latest versions for Compose, while the others use only stable versions. Choose the one that matches your Compose version, considering this table:
| Compose Version | datetime-wheel-picker Version |
|---|---|
| Compose 1.7 | |
| Compose 1.8 | |
| Compose 1.9 |
- Add the Maven Central repository if it is not already there:
repositories {
mavenCentral()
}- In Compose multiplatform projects, add a dependency to the commonMain source set dependencies:
kotlin {
sourceSets {
val commonMain by getting {
dependencies {
implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
}
}
}
}
- To use the library in a single-platform project (such as Android project), add a dependency to the dependencies block:
dependencies {
implementation("io.github.darkokoa:datetime-wheel-picker:<version>")
implementation("org.jetbrains.kotlinx:kotlinx-datetime:0.7.1")
}- If your minimum Android platform's API level (minSdk) < 26, please enable Desugaring like this:
compileOptions {
isCoreLibraryDesugaringEnabled = true
}
//...
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}Released under the Apache License, Version 2.0.




