🕘

【Android】MediaStore の DATE_TAKEN / DATE_ADDED について

2021/03/08に公開

Media.DATE_TAKENDATE_ADDEDカラムのタイムスタンプについて勘違いしていることがあったので、まとめておきたいと思います。

DATE_TAKEN : ミリ秒 / DATE_ADDED : 秒

UNIXエポック(1970年1月1日午前0時0分0秒(UTC))を基準に、DATE_TAKENは経過日数をミリ秒で、DATE_ADDEDは秒で表したタイムスタンプを持っています。

DATE_TAKENDATE_ADDEDのタイムスタンプは、以下のようになっています

  • DATE_TAKEN : 1111295661000
  • DATE_ADDED : 1602652291

DATE_TAKENは、Android 10(Android Q/API Level 29)から追加されたカラムなので、使用するとき以下のような判定が必要です。

val column = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
  MediaStore.Images.Media.DATE_TAKEN
} else {
  MediaStore.Images.Media.DATE_ADDED
}

タイムスタンプに関する単語について

UTC

  • Coordinated Universal Time の略
  • 協定世界時のこと
  • 世界標準で使われている時間
  • 日本(JST/日本標準時)との時差は「9時間」で、UTC が「09:00」なら日本は「18:00」になる

UNIX タイムスタンプ

  • 1970年1月1日午前0時0分0秒を基準にして、経過日数を秒で表したもの

UNIX エポック

  • 1970年1月1日午前0時0分0秒のこと

実装例 : 日時を指定して端末に保存されている写真を取得する

特定の日時以降に撮影された写真の URI を取得する実装です。

日時の取り扱いには ThreeTenABP ライブラリを使用しています。

app / build.gradle

implementation 'com.jakewharton.threetenabp:threetenabp:1.3.0'
fun loadPhotoUris(context: Context, dateTime: LocalDateTime): List<Uri> {
        val uris = mutableListOf<Uri>()
        // 取得したいカラムを指定する
        val projection: Array<String> = arrayOf(MediaStore.Images.Media._ID)
        // 検索条件 : 特定の日時以降に保存された画像を取得する
        val selection = "${MediaStore.Images.Media.DATE_ADDED} >= ?"
	val timestamp = toTimestamp(dateTime).toString()
	// selection の「?」に入る値
        val selectionArgs: Array<String> = arrayOf(timestamp)
        // DATE_ADDED で昇順にする
        val sortOrder = "${MediaStore.Images.Media.DATE_ADDED} ASC"

        context.contentResolver.query(
            MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
            projection,
            selection,
            selectionArgs,
            sortOrder
        ).use { cursor ->
            cursor ?: return@use
            val columnIndex = cursor.getColumnIndexOrThrow(MediaStore.Images.Media._ID)
            while (cursor.moveToNext()) {
                val imageId = cursor.getLong(columnIndex)
                val uri = Uri.withAppendedPath(
                    MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                    imageId.toString()
                )
                uris.add(uri)
            }
        }
        return uris
    }

    private fun toTimestamp(dateTime: LocalDateTime): Long {
        // JST に変換
        val zonedDateTime = dateTime.atZone(ZoneId.of("UTC+09:00"))
        return zonedDateTime.toEpochSecond()
    }

Discussion