Question
How can I get the current local date—day, month, and year—and the current time—hours, minutes, and seconds—in a Kotlin Android app?
I tried using:
val now = LocalDateTime.now()
but Android Studio reports that this call requires API level 26 while my app's minimum SDK version is 21. How can I obtain the current local date and time while supporting older Android versions?
Short Answer
You will learn why LocalDateTime.now() has an Android API-level warning, how local time depends on a time zone, and how to use the modern java.time API on Android API 21+ with core library desugaring. You will also see a legacy Calendar alternative for projects that cannot use desugaring.
Concept
LocalDateTime is part of Java's modern date and time API, called java.time. It represents a calendar date and clock time, such as 2025-03-08T14:30:45.
On Android, java.time is built into the platform starting at API level 26. Therefore, calling LocalDateTime.now() directly causes a warning when your app supports devices below API 26.
For Android apps with a minimum SDK below 26, the preferred solution is usually core library desugaring. Desugaring lets the Android build tools provide supported Java language and library APIs, including much of java.time, on older Android devices.
A local date and time is based on a time zone. LocalDateTime.now() uses the device's default time zone. For example, the same instant may be 09:00 in one location and 14:00 in another. If you need to record one exact point in time for storage or an API, use an Instant; convert it to local time only when displaying it.
Mental Model
Think of an Instant as a timestamp stamped on a worldwide package: it identifies one exact moment everywhere.
A LocalDateTime is the date and time printed on a wall clock: 08 March, 14:30. A wall-clock reading only makes complete sense when you know where that clock is located.
ZoneId.systemDefault() means “use the time zone currently configured on this device.” LocalDateTime.now() effectively asks the device: “What does your local wall clock say right now?”
Syntax and Examples
Use LocalDateTime.now() after enabling core library desugaring for Android API 21+.
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
val now = LocalDateTime.now()
val formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")
val readableDateTime = now.format(formatter)
println(readableDateTime)
// Example: 08/03/2025 14:30:45
now contains separate date and time values:
val day = now.dayOfMonth
val month = now.monthValue
val year = now.year
val hour = now.hour
val minute = now.minute
val second = now.second
To support Android versions below API 26, enable desugaring in your app module's build.gradle.kts:
android {
compileOptions {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
isCoreLibraryDesugaringEnabled = true
}
}
dependencies {
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.5")
}
If your project uses Groovy Gradle files (build.gradle), the equivalent setting is:
android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
coreLibraryDesugaringEnabled true
}
}
dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:2.1.5'
}
Once configured, import java.time.LocalDateTime, not an Android-specific replacement.
Step by Step Execution
Consider this example:
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
fun currentLocalTimestamp(): String {
val now = LocalDateTime.now()
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
return now.format(formatter)
}
Step by step:
LocalDateTime.now()reads the current date and time using the device's default time zone.- The result is stored in
now, for example2025-03-08T14:30:45.123. DateTimeFormatter.ofPattern(...)creates rules for display:yyyy: four-digit yearMM: two-digit monthdd: two-digit dayHH: hour in 24-hour timemm: minutesss: seconds
now.format(formatter)converts the date-time object into text such as2025-03-08 14:30:45.- The function returns the formatted text.
The formatter changes only the displayed string. The LocalDateTime value itself remains a date-time object that can be compared or manipulated.
Real World Use Cases
- Activity logs: Show when a user created a note, submitted a form, or completed a task.
- Booking interfaces: Display a locally understandable appointment time to the user.
- File names: Add a timestamp such as
report-2025-03-08-143045.txt. - Daily features: Determine today's date for a habit tracker, attendance screen, or “daily challenge.”
- Local notifications: Build a schedule based on the user's local calendar time.
- Data display: Convert a server timestamp into the device's local date and time before showing it in the UI.
For server communication and long-term event storage, prefer storing an Instant or an ISO-8601 timestamp with an offset. Local time alone can become ambiguous when time zones or daylight-saving rules change.
Real Codebase Usage
In real Android projects, developers commonly separate time acquisition, storage, and presentation.
Get an exact current moment
import java.time.Instant
val createdAt = Instant.now()
Use this for records sent to an API or saved in a database when the event must mean the same moment everywhere.
Convert an instant for local display
import java.time.Instant
import java.time.LocalDateTime
import java.time.ZoneId
val localTime = LocalDateTime.ofInstant(
Instant.now(),
ZoneId.systemDefault()
)
Keep formatting near the UI
import java.time.LocalDateTime
import java.time.format.DateTimeFormatter
import java.util.Locale
val formatter = DateTimeFormatter.ofPattern("dd MMM yyyy, HH:mm", Locale.getDefault())
val label = LocalDateTime.now().format(formatter)
For user-facing dates, developers often use a formatter with Locale.getDefault() so month names and formatting conventions can follow the user's language and region.
Avoid creating date strings too early in your business logic. Keep date-time values as Instant, LocalDate, or LocalDateTime objects until they must be displayed or serialized.
Common Mistakes
Using LocalDateTime without Android desugaring
This is valid Kotlin, but it is not available on Android API levels below 26 unless desugaring is enabled:
val now = LocalDateTime.now()
Enable core library desugaring, or use Calendar in a legacy-only project.
Confusing mm and MM
val wrong = DateTimeFormatter.ofPattern("dd/mm/yyyy")
Lowercase mm means minutes, not months. Use uppercase MM for a numeric month:
val correct = DateTimeFormatter.ofPattern("dd/MM/yyyy")
Using hh when 24-hour time is intended
HHis 00–23 (24-hour clock).hhis 01–12 (12-hour clock) and usually needs anamarker such as AM or PM.
val twelveHour = DateTimeFormatter.ofPattern("hh:mm:ss a")
val twentyFourHour = DateTimeFormatter.ofPattern("HH:mm:ss")
Storing a formatted local string as the source of truth
A value such as 08/03/2025 14:30:45 has no time-zone information and can be interpreted differently in different locales. Store an Instant or a properly defined date-time value; format it for display later.
Reusing SimpleDateFormat across threads
SimpleDateFormat is mutable and not thread-safe. If you must use it in legacy code, create it for the operation or carefully control access. Prefer immutable DateTimeFormatter when using java.time.
Forgetting that device time can be changed
The user or device may change the clock or time zone. Do not use local device time as a secure source for billing, authentication, or fraud-sensitive decisions; use trusted server time where needed.
Comparisons
| Need | Best type or API | Why |
|---|---|---|
| Current date and clock time on the device | LocalDateTime.now() | Convenient local date and time for display or local rules. |
| Today's date only | LocalDate.now() | No unnecessary hour, minute, or second values. |
| Current time only | LocalTime.now() | Useful for local time-of-day logic. |
| One exact global moment | Instant.now() | Independent of a user's location and time zone. |
| Date and time with a named time zone | ZonedDateTime | Keeps both the clock time and zone rules. |
| Older Android code without desugaring | Calendar | Available on older Android versions, but more error-prone. |
A legacy Calendar example:
import java.util.Calendar
val calendar = Calendar.getInstance()
val year = calendar.get(Calendar.YEAR)
val month = calendar.get(Calendar.MONTH) + 1 // Calendar months start at 0
val day = calendar.get(Calendar.DAY_OF_MONTH)
val hour = calendar.get(Calendar.HOUR_OF_DAY)
val minute = calendar.get(Calendar.MINUTE)
val second = calendar.get(Calendar.SECOND)
Calendar.MONTH is zero-based, so January is 0. This is one reason java.time is usually easier and safer to use.
Cheat Sheet
// Current local date and time
val now = LocalDateTime.now()
// Individual fields
val year = now.year
val month = now.monthValue // 1 through 12
val day = now.dayOfMonth
val hour = now.hour // 0 through 23
val minute = now.minute
val second = now.second
// Format for display
val text = now.format(
DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")
)
// Current exact moment for storage or APIs
val instant = Instant.now()
// Convert an instant to the device's local time
val local = LocalDateTime.ofInstant(instant, ZoneId.systemDefault())
Rules to remember:
- Android API 26+ includes
java.timenatively. - For Android API 21–25, enable core library desugaring to use
java.time. MM= month;mm= minute.HH= 24-hour clock;hh= 12-hour clock.LocalDateTimehas no stored time-zone or offset.- Prefer
Instantfor timestamps shared with servers or users in other time zones.
FAQ
Why does LocalDateTime.now() require API 26 on Android?
Android added the java.time API to the platform at API 26. For lower Android versions, enable core library desugaring or use an older API such as Calendar.
Does LocalDateTime.now() use local time?
Yes. It uses the device's current default time zone.
How do I get only the current date in Kotlin?
Use:
val today = LocalDate.now()
How do I get only the current time in Kotlin?
Use:
val time = LocalTime.now()
What format pattern should I use for day, month, year, and time?
A common 24-hour pattern is:
"dd/MM/yyyy HH:mm:ss"
Should I use Date or LocalDateTime in new Kotlin Android code?
Prefer java.time types such as Instant, LocalDate, and LocalDateTime for new code. They have clearer responsibilities and safer APIs than the older Date and Calendar classes.
How can I support Android API 21 with LocalDateTime?
Enable core library desugaring in your Android Gradle configuration and add the desugar_jdk_libs dependency.
Is LocalDateTime safe for timestamps sent to an API?
Not by itself, because it does not include a time zone or offset. Use Instant or an offset-aware ISO-8601 value for API timestamps.
Mini Project
Description
Build a small Kotlin utility that creates a local timestamp suitable for an activity log. It demonstrates obtaining the device's current local time and formatting it consistently for display.
Goal
Create a function that returns a message such as Task completed at 08/03/2025 14:30:45.
Requirements
Return the current date and time in the device's local time zone.|Use a 24-hour format containing day, month, year, hour, minute, and second.|Use LocalDateTime and DateTimeFormatter.|Ensure the Android project supports API 21+ with core library desugaring enabled.
Keep learning
Related questions
Accessing Kotlin Extension Functions from Java
Learn how Kotlin extension functions are compiled and how to call them correctly from Java with clear examples and common pitfalls.
Add a Maven Repository URL in Gradle Kotlin DSL (build.gradle.kts)
Learn how to add Maven Central and a custom Maven repository URL in Gradle Kotlin DSL using build.gradle.kts syntax.
Allow HTTP and HTTPS in Android 9 Pie with Network Security Configuration
Learn how Android 9 Pie handles cleartext HTTP traffic and how to allow HTTP and HTTPS safely using network security config.