Avatar ·

Как получить текущий timestamp (метку времени) в Android на Kotlin?

Всем привет! Я начинающий Android-разработчик, пишу на Kotlin. Столкнулся с, казалось бы, простой задачей: мне нужно получить текущий timestamp (метку времени) в моём приложении, чтобы, например, сохранить время создания записи в базу данных или отправить на сервер. Я перепробовал несколько вариантов, но запутался в разных API. Раньше в Java я использовал `System.currentTimeMillis()`, но в Kotlin это тоже работает, и я получаю какое-то длинное число. Это правильно? Но я слышал, что это не очень хорошо, и нужно использовать `Instant.now()` или `Calendar.getInstance()`. А ещё есть `Date()`. Подскажите, пожалуйста, какой способ считается правильным и современным для Android (API 26+)? Мне нужно получить timestamp в формате Unix (количество миллисекунд с 1 января 1970 года). Вот пример моего кода, который я сейчас использую, но не уверен, что он хорош: ```kotlin val currentTime = System.currentTimeMillis() Log.d("MyApp", "Current timestamp: $currentTime") ``` Будет ли этот код работать корректно на всех устройствах? Или есть более надёжные и читаемые способы? Заранее спасибо за помощь! <<>>

Правильный и современный способ получения timestamp в Android/Kotlin

Ваш код с System.currentTimeMillis() абсолютно рабочий и возвращает корректный Unix timestamp в миллисекундах. Однако для современной разработки на Kotlin под Android (с API 26 и выше) рекомендуется использовать API из пакета java.time, который был добавлен в Java 8. Это более чистый, типобезопасный и удобный подход.

Вот основной способ с использованием java.time.Instant:

import java.time.Instant

fun getCurrentTimestamp(): Long {
    return Instant.now().toEpochMilli()
}

// Использование:
val timestamp = getCurrentTimestamp()
println("Unix timestamp (мс): $timestamp")

Почему это лучше, чем System.currentTimeMillis()?

  • Типобезопасность: Instant явно представляет момент времени, а не просто число.
  • Читаемость: Код самодокументируемый — сразу понятно, что мы работаем с меткой времени.
  • Гибкость: Вы легко можете преобразовать Instant в другие форматы (дата, время, строковое представление).
  • Тестируемость: Можно легко замокать или подменить Clock для тестов.

Если вам нужен timestamp в секундах (а не миллисекундах):

val timestampSeconds = Instant.now().epochSecond

Как получить timestamp в виде строки (для отображения)?

Часто вам нужно не просто число, а человекочитаемая дата. Вот как это сделать:

import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter

fun getCurrentTimestampAsString(): String {
    val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
        .withZone(ZoneId.systemDefault())
    return formatter.format(Instant.now())
}

// Пример: "2023-10-27 15:30:45"

Что делать, если ваше приложение поддерживает API ниже 26?

Используйте библиотеку ThreeTen ABP (ThreeTen Android Backport), которая добавляет поддержку java.time на старые устройства. Подключите зависимость в build.gradle:

implementation 'com.jakewharton.threetenabp:threetenabp:1.4.6'

Затем инициализируйте в Application.onCreate():

class MyApp : Application() {
    override fun onCreate() {
        super.onCreate()
        AndroidThreeTen.init(this)
    }
}

После этого вы можете использовать тот же самый код с Instant.now() — он будет работать на всех API.

Полный пример для современного Android-приложения:

import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime

class TimeUtils {
    companion object {
        fun nowMillis(): Long = Instant.now().toEpochMilli()
        
        fun nowSeconds(): Long = Instant.now().epochSecond
        
        fun nowFormatted(pattern: String = "dd.MM.yyyy HH:mm:ss"): String {
            val formatter = java.time.format.DateTimeFormatter.ofPattern(pattern)
            return ZonedDateTime.now().format(formatter)
        }
    }
}

// Использование:
val millis = TimeUtils.nowMillis()       // 1698413456789
val seconds = TimeUtils.nowSeconds()     // 1698413456
val dateStr = TimeUtils.nowFormatted()   // "27.10.2023 15:30:56"

Итог: Используйте Instant.now().toEpochMilli() для Unix timestamp и java.time API для всех операций с датами. Это современный, поддерживаемый Google и сообществом подход. System.currentTimeMillis() тоже работает, но уступает по удобству и читаемости.

<<>>

Альтернативный подход: использование Calendar или Date (для старых проектов)

Если вы работаете с легаси-кодом или ваше приложение не использует java.time (например, из-за ограничений по API), можно использовать Calendar или Date. Эти классы всё ещё поддерживаются, хотя и считаются устаревшими для новых проектов.

import java.util.Calendar
import java.util.Date

// Способ 1: через Calendar
val timestampFromCalendar = Calendar.getInstance().timeInMillis

// Способ 2: через Date
val timestampFromDate = Date().time

Когда это может быть полезно?

  • Вы поддерживаете API < 26 и не хотите подключать ThreeTen ABP.
  • Вы работаете с библиотеками, которые ожидают Date или Calendar.
  • Вы только начинаете и не хотите усложнять проект дополнительными зависимостями.

Недостатки этого подхода:

  • Date и Calendar — mutable (изменяемые), что может привести к багам в многопоточных средах.
  • API менее удобен: например, для форматирования даты нужно создавать SimpleDateFormat.
  • Google и Kotlin-сообщество рекомендуют переходить на java.time.

Вывод: Если ваш проект новый, используйте java.time. Если старый и вы не хотите рефакторить — оставьте Calendar, но в новом коде всё равно переходите на современный API.