refactor(time): Centralize time handling with kotlinx-datetime (#4545)

Signed-off-by: James Rich <2199651+jamesarich@users.noreply.github.com>
This commit is contained in:
James Rich 2026-02-13 20:01:07 -06:00 committed by GitHub
parent da04448dee
commit 5ca2ab4695
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
86 changed files with 993 additions and 663 deletions

View file

@ -37,6 +37,7 @@ import org.meshtastic.core.database.entity.Packet
import org.meshtastic.core.database.entity.ReactionEntity
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.PortNum
@RunWith(AndroidJUnit4::class)
@ -71,7 +72,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = contactKey,
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = false,
data = DataPacket(DataPacket.ID_BROADCAST, 0, "Message $it!"),
)
@ -153,7 +154,7 @@ class PacketDaoTest {
@Test
fun test_clearUnreadCount() = runBlocking {
val timestamp = System.currentTimeMillis()
val timestamp = nowMillis
testContactKeys.forEach { contactKey ->
packetDao.clearUnreadCount(contactKey, timestamp)
val unreadCount = packetDao.getUnreadCount(contactKey)
@ -180,7 +181,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = "test",
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = true,
data = DataPacket(to = DataPacket.ID_BROADCAST, channel = 0, text = "Test").copy(id = packetId),
packetId = packetId,
@ -203,7 +204,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = "test",
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = true,
data = DataPacket(to = DataPacket.ID_BROADCAST, channel = 0, text = "Test"),
sfpp_hash = hashByteString,
@ -227,7 +228,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = "test",
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = true,
data = DataPacket(to = DataPacket.ID_BROADCAST, channel = 0, text = "Test"),
sfpp_hash = hashByteString,
@ -262,7 +263,7 @@ class PacketDaoTest {
replyId = 123,
userId = "sender",
emoji = "👍",
timestamp = System.currentTimeMillis(),
timestamp = nowMillis,
sfpp_hash = hashByteString,
)
@ -290,7 +291,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = "test",
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = true,
data = DataPacket(to = "target", channel = 0, text = "Hello").copy(id = initialId),
packetId = initialId,
@ -322,7 +323,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = "test",
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = true,
data = DataPacket(to = toId, channel = 0, text = "Match me").copy(from = fromId, id = packetId),
packetId = packetId,
@ -356,7 +357,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = filteredContactKey,
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = false,
data = DataPacket(DataPacket.ID_BROADCAST, 0, "Filtered message"),
filtered = true,
@ -380,7 +381,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = contactKey,
received_time = System.currentTimeMillis() + i,
received_time = nowMillis + i,
read = false,
data = DataPacket(DataPacket.ID_BROADCAST, 0, "Filtered $i"),
filtered = true,
@ -428,7 +429,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = contactKey,
received_time = System.currentTimeMillis() + index,
received_time = nowMillis + index,
read = false,
data = DataPacket(DataPacket.ID_BROADCAST, 0, text),
filtered = false,
@ -443,7 +444,7 @@ class PacketDaoTest {
myNodeNum = myNodeNum,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = contactKey,
received_time = System.currentTimeMillis() + normalMessages.size + index,
received_time = nowMillis + normalMessages.size + index,
read = true, // Filtered messages are marked as read
data = DataPacket(DataPacket.ID_BROADCAST, 0, text),
filtered = true,

View file

@ -34,6 +34,7 @@ import kotlinx.coroutines.sync.Mutex
import kotlinx.coroutines.sync.withLock
import kotlinx.coroutines.withContext
import org.meshtastic.core.di.CoroutineDispatchers
import org.meshtastic.core.model.util.nowMillis
import java.io.File
import java.security.MessageDigest
import javax.inject.Inject
@ -115,7 +116,7 @@ class DatabaseManager @Inject constructor(private val app: Application, private
inline fun <T> withDb(block: (MeshtasticDatabase) -> T): T = block(currentDb.value)
private fun markLastUsed(dbName: String) {
prefs.edit().putLong(lastUsedKey(dbName), System.currentTimeMillis()).apply()
prefs.edit().putLong(lastUsedKey(dbName), nowMillis).apply()
}
private fun lastUsed(dbName: String): Long {

View file

@ -31,6 +31,7 @@ import org.meshtastic.core.database.entity.PacketEntity
import org.meshtastic.core.database.entity.ReactionEntity
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.ChannelSettings
@Suppress("TooManyFunctions")
@ -347,7 +348,7 @@ interface PacketDao {
} else if (until == 0L) { // unmute
0L
} else {
System.currentTimeMillis() + until
nowMillis + until
}
getContactSettings(contact)?.copy(muteUntil = absoluteMuteUntil)

View file

@ -22,6 +22,7 @@ import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable
import org.meshtastic.core.model.DeviceHardware
import org.meshtastic.core.model.NetworkDeviceHardware
import org.meshtastic.core.model.util.nowMillis
@Serializable
@Entity(tableName = "device_hardware")
@ -34,7 +35,7 @@ data class DeviceHardwareEntity(
val hwModel: Int,
@ColumnInfo(name = "hw_model_slug") val hwModelSlug: String,
val images: List<String>?,
@ColumnInfo(name = "last_updated") val lastUpdated: Long = System.currentTimeMillis(),
@ColumnInfo(name = "last_updated") val lastUpdated: Long = nowMillis,
@ColumnInfo(name = "partition_scheme") val partitionScheme: String? = null,
@PrimaryKey @ColumnInfo(name = "platformio_target") val platformioTarget: String,
@ColumnInfo(name = "requires_dfu") val requiresDfu: Boolean?,
@ -51,7 +52,7 @@ fun NetworkDeviceHardware.asEntity() = DeviceHardwareEntity(
hwModel = hwModel,
hwModelSlug = hwModelSlug,
images = images,
lastUpdated = System.currentTimeMillis(),
lastUpdated = nowMillis,
partitionScheme = partitionScheme,
platformioTarget = platformioTarget,
requiresDfu = requiresDfu,

View file

@ -22,6 +22,7 @@ import androidx.room.PrimaryKey
import kotlinx.serialization.Serializable
import org.meshtastic.core.model.DeviceVersion
import org.meshtastic.core.model.NetworkFirmwareRelease
import org.meshtastic.core.model.util.nowMillis
@Serializable
@Entity(tableName = "firmware_release")
@ -31,7 +32,7 @@ data class FirmwareReleaseEntity(
@ColumnInfo(name = "release_notes") val releaseNotes: String = "",
@ColumnInfo(name = "title") val title: String = "",
@ColumnInfo(name = "zip_url") val zipUrl: String = "",
@ColumnInfo(name = "last_updated") val lastUpdated: Long = System.currentTimeMillis(),
@ColumnInfo(name = "last_updated") val lastUpdated: Long = nowMillis,
@ColumnInfo(name = "release_type") val releaseType: FirmwareReleaseType = FirmwareReleaseType.STABLE,
)
@ -41,7 +42,7 @@ fun NetworkFirmwareRelease.asEntity(releaseType: FirmwareReleaseType) = Firmware
releaseNotes = releaseNotes,
title = title,
zipUrl = zipUrl,
lastUpdated = System.currentTimeMillis(),
lastUpdated = nowMillis,
releaseType = releaseType,
)
@ -61,7 +62,7 @@ data class FirmwareRelease(
val releaseNotes: String = "",
val title: String = "",
val zipUrl: String = "",
val lastUpdated: Long = System.currentTimeMillis(),
val lastUpdated: Long = nowMillis,
val releaseType: FirmwareReleaseType = FirmwareReleaseType.STABLE,
)

View file

@ -30,6 +30,8 @@ import org.meshtastic.core.model.EnvironmentMetrics
import org.meshtastic.core.model.MeshUser
import org.meshtastic.core.model.NodeInfo
import org.meshtastic.core.model.Position
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.core.model.util.nowSeconds
import org.meshtastic.core.model.util.onlineTimeThreshold
import org.meshtastic.proto.DeviceMetadata
import org.meshtastic.proto.HardwareModel
@ -100,7 +102,7 @@ data class NodeWithRelations(
data class MetadataEntity(
@PrimaryKey val num: Int,
@ColumnInfo(name = "proto", typeAffinity = ColumnInfo.BLOB) val proto: DeviceMetadata,
val timestamp: Long = System.currentTimeMillis(),
val timestamp: Long = nowMillis,
)
@Suppress("MagicNumber")
@ -181,7 +183,7 @@ data class NodeEntity(
val ERROR_BYTE_STRING: ByteString = ByteArray(32) { 0 }.toByteString()
fun currentTime() = (System.currentTimeMillis() / 1000).toInt()
fun currentTime() = nowSeconds.toInt()
}
fun toModel() = Node(

View file

@ -28,6 +28,7 @@ import org.meshtastic.core.database.model.Node
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.MessageStatus
import org.meshtastic.core.model.util.getShortDateTime
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.User
data class PacketEntity(
@ -126,7 +127,7 @@ data class ContactSettings(
@ColumnInfo(name = "filtering_disabled", defaultValue = "0") val filteringDisabled: Boolean = false,
) {
val isMuted
get() = System.currentTimeMillis() <= muteUntil
get() = nowMillis <= muteUntil
}
data class Reaction(

View file

@ -31,6 +31,7 @@ import org.meshtastic.core.database.MeshtasticDatabase
import org.meshtastic.core.database.entity.MyNodeEntity
import org.meshtastic.core.database.entity.Packet
import org.meshtastic.core.model.DataPacket
import org.meshtastic.core.model.util.nowMillis
import org.meshtastic.proto.ChannelSettings
import org.meshtastic.proto.PortNum
@ -155,7 +156,7 @@ class MigrationTest {
myNodeNum = 42424242,
port_num = PortNum.TEXT_MESSAGE_APP.value,
contact_key = "$channel!broadcast",
received_time = System.currentTimeMillis(),
received_time = nowMillis,
read = false,
data = DataPacket(to = DataPacket.ID_BROADCAST, channel = channel, text = text),
),