Rails：Sqlite3のタイムゾーン変更について

# 前提
使用フレームワーク：　Ruby on Rals

作成したもの：　railsを使ったごく単純な掲示版風アプリ（今回詳細は省きます）

使用するDBエンジン：　SQLite３(新規アプリ立ち上げ時のデフォルトのまま)

やりたいこと：　デフォルトではレコードの作成日時と更新日時がUTC表記になっているので、テーブル上の表記をJSTに変更したい

以下が作成したDBのスキーマ（後述のオチを知る前に作成したもの）
```
## Table：posts
| Column Name | Data Type | Nullable |
|-------------|-----------|----------|
| title       | string    |          |
| content     | text      |          |
| created_at  | datetime  |   false  |
| updated_at  | datetime  |   false  |

```
画像だと判別できませんが、created_atとupdated_at内のレコードがUTCとなっています。（実際に作成した時間はレコード内表記の時間+9）

![スクリーンショット 2024-04-03 16.19.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/164e4a47-be98-fa6f-8cbc-18377b938ed7.png)

始めに申し上げておきますと、SQLiteにはDB内タイムスタンプの表示形式を変更するための直接的な方法はありません。それをひたすらJST表記に直そうと悪戦苦闘したわけですが、そもそもSQLiteは日付/時刻型のデータ型を持っていないという**間抜けなオチ**がありまして…。お恥ずかしながらスキーマ書いてた時は存じ上げませんでした。

今回初めて知ったのですが、Date型に見える上記のタイムスタンプは**テキスト型で保持しているだけ**だそうです。最初に[公式リファレンス](https://www.sqlite.org/)等で確認しておくべきでしたね。
![スクリーンショット 2024-04-03 19.12.31.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/3b206cfe-8c19-279a-1c70-db2f906b76bb.png)


## 試したこと （供養も兼ねて書かせていただきます）
### その１
application.rbの編集。（コメントアウトを外す）
```ruby
#

require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module RubydemoBbs
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    # config.time_zone = "Central Time (US & Canada)"
    # config.eager_load_paths << Rails.root.join("extras")
  end
end
```
調べてみるとこのファイルにRailsのタイムゾーン設定が記述されているようなので、
```ruby

# config.time_zone = "Central Time (US & Canada)"のコメントアウトを外す
config.time_zone = "Central Time (US & Canada)"
```

```ruby
# time_zoneを"Tokyo"へ修正
 config.time_zone = "Tokyo"
```
上記の状態でDBを再度確認。
**が、DBの表記は変わらず。**
ですが、以下画像のようにブラウザ側の表示が
![スクリーンショット 2024-04-03 18.07.45.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/acff98c0-fdc6-d2f3-0e7e-83bb1302d9c2.png)
から
![スクリーンショット 2024-04-03 18.10.17.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/33e1a300-247e-38cf-cda6-2c72815946d5.png)
アプリ側はJTS表記へ変わるようです。

### その２
再びapplication.rbの編集。（オプションを追加する）
```ruby
require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module RubydemoBbs
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    config.time_zone = "Tokyo"
    
    # オプション追加
    config.active_record.time_zone_aware_types = [:datetime, :time]
    # config.eager_load_paths << Rails.root.join("extras")
  end
end

```
上記のオプションを追加しました。

:::note 
**config.active_record.time_zone_aware_types = [:datetime, :time]について**

Active Recordがタイムゾーンを含む値を処理する際に、データ型を指定して渡すことのできるオプションです。
保存・取得を行う際に指定したデータ型に変換してねという設定です。指定するデータ型はハッシュの形式で書きます。この場合はタイムゾーン（datetime）、時刻(time)それぞれのデータ型のカラムに対して変換しているような理解です。
<font color = red>※注意※　　
アプリケーション全体の挙動に影響を及ぼす設定変更になるので、試す際はくれぐれも慎重に、かつ自己責任で行ってください。
</font>
:::

こちらはDB、ブラウザ表示ともに変化なし。

## ならもうSQLでなんとかできない？？
できません。
ですが、SELECT文で取得した作成日時と更新日時をJTC表記風に変換することは可能です。
試したことではあるので一応書いておきます。

```SQL
SELECT datetime(created_at, 'localtime') AS local_created_at
FROM posts;
```
![スクリーンショット 2024-04-03 18.42.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/062218f1-0a01-0184-ad74-225298cd44f8.png)

datetime 関数を使用して created_at 列の値をローカルタイムゾーンに変換しています。
新たに「local_created_at」というカラムが出来てそれを取得することはできました。
でもやりたいのはそういうことじゃない・・・。

## 最終的に
答えはapplication.rbにありました。

```ruby
require_relative "boot"

require "rails/all"

# Require the gems listed in Gemfile, including any gems
# you've limited to :test, :development, or :production.
Bundler.require(*Rails.groups)

module RubydemoBbs
  class Application < Rails::Application
    # Initialize configuration defaults for originally generated Rails version.
    config.load_defaults 7.0

    # Configuration for the application, engines, and railties goes here.
    #
    # These settings can be overridden in specific environments using the files
    # in config/environments, which are processed later.
    #
    config.time_zone = "Tokyo"
    
    #オプションをここに再度追加
    config.active_record.default_timezone = :local
    # config.eager_load_paths << Rails.root.join("extras")
  end
end
```
**config.active_record.default_timezone = :local**

最初にconfig.time_zoneを編集していたのがここで活きました。
タイムゾーンを考慮したデータをDBに保存する場合に、ローカルのタイムゾーンに変換するという設定のようです。

![スクリーンショット 2024-04-03 18.49.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3511203/5c1736a0-71ee-4440-66ee-f3fbf518b013.png)

すると、当初やりたかったことが形にできました。
3行目が編集前に投稿したデータ、４行目が編集後に投稿したデータになります。編集前にすでに格納済みだった日時データには反映されないみたいですね～。
ちなみに今回スキーマは変更していないので再度マイグレーションは行なっておりません。
が、今のところ問題は起きていませんでした。

## 終わり
読んでいただきありがとうございました。
まだ知らないことばかりですね。日々痛感します。

**参考**
[意外と知らないTimestamp](https://qiita.com/kizuna0224/items/b1b3f52ef39e8bc1a453)
[SQLiteで日付時刻を扱う際のポイント](https://qiita.com/TomK/items/132831ab45e2aba822a8)