MediaStoreの「DATE_TAKEN」「DATE_ADDED」について

2 min read読了の目安(約2500字

MediaStore.Images.Media.DATE_TAKENカラムと、MediaStore.Images.Media.DATE_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 loadTakenPhotoUris(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()
    }