回答:
MySQLのタイムスタンプは、通常、レコードへの変更を追跡するために使用され、レコードが変更されるたびに更新されることがよくあります。特定の値を保存する場合は、日時フィールドを使用する必要があります。
UNIXタイムスタンプとネイティブMySQL日時フィールドのどちらを使用するかを決定したい場合は、ネイティブ形式を使用してください。その方法でMySQL内で計算を行うことができます。PHPで
操作したい場合、レコードをクエリするときに("SELECT DATE_ADD(my_datetime, INTERVAL 1 DAY)")
値の形式をUNIXタイムスタンプ("SELECT UNIX_TIMESTAMP(my_datetime)")
に変更するのは簡単です。
DATETIME
、日付(カレンダーにある)と時刻(壁掛け時計で確認できる)をTIMESTAMP
表し、明確に定義された時点を表すことです。アプリケーションがタイムゾーンを処理する場合、これは非常に重要です。「2010-09-01 16:31:00」はどれくらい前ですか?それはあなたがどのタイムゾーンにいるかに依存します。私にとってそれはほんの数秒前でした、あなたにとってそれは将来の時間を表すかもしれません。'1970-01-01 00:00:00 UTC'から1283351460秒と言うと、私がいつ話しているのか正確にわかります。(以下のNirの優れた答えを参照してください)。[欠点:有効範囲]。
MySQL 5以降では、TIMESTAMP値は現在のタイムゾーンからUTCに変換されて格納され、取得のためにUTCから現在のタイムゾーンに変換されます。(これは、TIMESTAMPデータ型でのみ発生し、DATETIMEなどの他の型では発生しません。)
デフォルトでは、各接続の現在のタイムゾーンはサーバーの時間です。時間帯は、MySQLサーバーの時間帯サポートで説明されているように、接続ごとに設定できます。
行のメタデータ(作成または変更された日付)以外には常にDATETIMEフィールドを使用します。
以下のように述べた MySQLのマニュアルに:
DATETIMEタイプは、日付と時刻の両方の情報を含む値が必要な場合に使用されます。MySQLは 'YYYY-MM-DD HH:MM:SS'形式でDATETIME値を取得して表示します。サポートされる範囲は「1000-01-01 00:00:00」から「9999-12-31 23:59:59」です。
...
TIMESTAMPデータ型の範囲は、 '1970-01-01 00:00:01' UTCから '2038-01-09 03:14:07' UTCです。MySQLのバージョンとサーバーが実行されているSQLモードに応じて、さまざまなプロパティがあります。
一般的に使用されているTIMESTAMPの下限に達する可能性が非常に高くなります(たとえば、誕生日の保存など)。
new Date().getTime()
、64ビットの値がすでに提供されています。
次の例はTIMESTAMP
、time-zone to 'america/new_york'
where DATETIME
が変更されていない後に日付タイプが値を変更した方法を示しています。
mysql> show variables like '%time_zone%';
+------------------+---------------------+
| Variable_name | Value |
+------------------+---------------------+
| system_time_zone | India Standard Time |
| time_zone | Asia/Calcutta |
+------------------+---------------------+
mysql> create table datedemo(
-> mydatetime datetime,
-> mytimestamp timestamp
-> );
mysql> insert into datedemo values ((now()),(now()));
mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime | mytimestamp |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 14:11:09 |
+---------------------+---------------------+
mysql> set time_zone="america/new_york";
mysql> select * from datedemo;
+---------------------+---------------------+
| mydatetime | mytimestamp |
+---------------------+---------------------+
| 2011-08-21 14:11:09 | 2011-08-21 04:41:09 |
+---------------------+---------------------+
私は私の回答を記事に変換したので、より多くの人がこの便利なMySQLを見つけることができます:日時とタイムスタンプのデータ型。
DATETIME
タイムゾーンの変更に伴って有効時間は変更されましたが、変更されTIMESTAMP
ませんでしたが、人間の表現は変更されました。
set time_zone="america/new_york"
です。
主な違いは、TIMESTAMPがtime_zone
設定の影響を受ける一方で、DATETIMEは定数であることです。
したがって、タイムゾーン間でクラスターを同期している場合、または将来的には同期している場合にのみ問題になります。
簡単に言えば、オーストラリアにデータベースがあり、そのデータベースのダンプを取得してアメリカのデータベースに同期またはデータを取り込む場合、TIMESTAMPは新しいタイムゾーンのイベントのリアルタイムを反映するように更新され、DATETIMEはまだauタイムゾーンのイベントの時刻を反映しています。
TIMESTAMPが使用されているはずのDATETIMEの使用例はFacebookにあります。Facebookのサーバーでは、タイムゾーン全体で発生した時刻が不明です。メッセージが実際に送信される前に、メッセージに返信していると言った会話がありました。(もちろん、これは、時刻が同期されているのではなく投稿されていた場合、メッセージングソフトウェアのタイムゾーン変換が悪いために発生した可能性もあります。)
この決定はセマンティックベースで行います。
(多かれ少なかれ)一定の時点を記録する必要がある場合は、タイムスタンプを使用します。たとえば、レコードがデータベースに挿入されたときや、ユーザーアクションが発生したときなどです。
日時を任意に設定・変更できる場合は日時フィールドを利用しています。たとえば、ユーザーが後で変更予定を保存できる場合です。
DATETIMEフィールドもTIMESTAMPフィールドも使用しないことをお勧めします。特定の日全体(誕生日など)を表す場合は、DATE型を使用しますが、それよりも具体的である場合は、単位の単位ではなく実際の瞬間を記録することにおそらく興味があります。時間(日、週、月、年)。DATETIMEまたはTIMESTAMPを使用する代わりに、BIGINTを使用し、エポック(Javaを使用している場合はSystem.currentTimeMillis())以降のミリ秒数を格納します。これにはいくつかの利点があります。
この問題は、金額(1.99ドル)をデータベースに保存する方法と密接に関連しています。あなたは10進数、またはデータベースのマネータイプ、またはすべての最悪のダブルを使用する必要がありますか?上記の同じ理由の多くのために、これらの3つのオプションはすべてひどいものです。解決策は、BIGINTを使用して金銭の価値をセントで保存し、ユーザーに値を表示するときにセントをドルに変換することです。データベースの仕事はデータを保存することであり、そのデータを解釈することではありません。データベース(特にOracle)に見られるこれらすべての派手なデータ型はほとんど追加せず、ベンダーロックインへの道のりを開始します。
DATETIMEのTIMESTAMPは4バイト対8バイトです。
http://dev.mysql.com/doc/refman/5.0/en/storage-requirements.html
しかし、scronideが言ったように、1970年の下限はあります。ただし、将来発生する可能性のあるすべてのことには最適です;)
TIMESTAMPは4バイトですが、DATETIMEでは8バイトです。
タイムスタンプもデータベース上で軽くなり、インデックスが速くなります。
DATETIMEタイプは、日付と時刻の両方の情報を含む値が必要な場合に使用されます。MySQLは 'YYYY-MM-DD HH:MM:SS'形式でDATETIME値を取得して表示します。サポートされる範囲は「1000-01-01 00:00:00」から「9999-12-31 23:59:59」です。
TIMESTAMPデータ型の範囲は、 '1970-01-01 00:00:01' UTCから '2038-01-09 03:14:07' UTCです。MySQLのバージョンとサーバーが実行されているSQLモードに応じて、さまざまなプロパティがあります。
本当にアプリケーション次第です。
Sanghaiでの予定のために、ニューヨークのサーバーにユーザーがタイムスタンプを設定することを検討してください。ユーザーがSanghaiで接続すると、東京のミラーサーバーから同じ予定のタイムスタンプにアクセスします。彼は東京時間の予定を、最初のニューヨーク時間からオフセットして見るでしょう。
したがって、予定やスケジュールなどのユーザーの時間を表す値の場合は、datetimeの方が適しています。サーバーの設定に関係なく、ユーザーは希望する正確な日付と時刻を制御できます。設定時刻は設定時刻であり、サーバーのタイムゾーン、ユーザーのタイムゾーン、または夏時間の計算方法の変更による影響はありません(変更されます)。
一方、支払いトランザクション、テーブル変更、ロギングなどのシステム時間を表す値には、常にタイムスタンプを使用します。サーバーを別のタイムゾーンに移動したり、異なるタイムゾーンのサーバー間を比較したりしても、システムは影響を受けません。
タイムスタンプもデータベース上で軽くなり、インデックスが速くなります。
最近のフロントエンドフレームワーク(Angular 1/2、react、Vueなど)では、UTCの日時を現地時間に簡単かつ自動的に変換できます。
さらに:
(サーバーのタイムゾーンを変更する可能性が高い場合を除く)
AngularJsの例
// back-end: format for angular within the sql query
SELECT DATE_FORMAT(my_datetime, "%Y-%m-%dT%TZ")...
// font-end Output the localised time
{{item.my_datetime | date :'medium' }}
ここで利用可能なすべてのローカライズされた時刻形式:https : //docs.angularjs.org/api/ng/filter/date
SET time_zone = '+0:00';
UTCの場合)。
timestamp
フィールドには、特殊なケースであるdatetime
フィールド。timestamp
特別なプロパティを持つ列を作成できます。作成時または更新時に自身を更新するように設定できます。
「より大きな」データベース用語でtimestamp
は、それにいくつかの特別なケースのトリガーがあります。
どれが正しいかは、あなたが何をしたいかに完全に依存します。
DATETIME、TIMESTAMP、DATEの比較
[.fraction]とは何ですか?
出典:
MySQLとPHPを使用する場合は、常にUnixタイムスタンプを使用します。これの主な理由は、PHPのデフォルトの日付メソッドがタイムスタンプをパラメーターとして使用するため、解析は必要ありません。
PHPで現在のUnixタイムスタンプを取得するにはtime();
、MySQLで行いますSELECT UNIX_TIMESTAMP();
。
私の経験から、挿入が1回だけ行われる日付フィールドが必要で、その特定のフィールドで更新やその他のアクションを実行したくない場合は、日付時刻を使用します。
たとえばuser
、REGISTRATION DATEフィールドを持つテーブルを考えてみます。そのuser
テーブルで、特定のユーザーが最後にログインした時刻を知りたい場合は、タイムスタンプタイプのフィールドを使用して、フィールドが更新されるようにします。
phpMyAdminからテーブルを作成している場合、デフォルト設定では、行の更新が発生したときにタイムスタンプフィールドが更新されます。タイムスタンプフィールドが行更新で更新されない場合は、次のクエリを使用して、タイムスタンプフィールドを自動更新できます。
ALTER TABLE your_table
MODIFY COLUMN ts_activity TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP;
タイムスタンプデータ型は日付と時刻を格納しますが、datetimeのように現在のタイムゾーン形式ではなくUTC形式で格納します。そして、データをフェッチすると、timestampは再びそれを現在のタイムゾーン時間に変換します。
たとえば、米国にいて、米国のタイムゾーンを持つサーバーからデータを取得するとします。次に、米国のタイムゾーンに従って日付と時刻を取得します。タイムスタンプデータタイプの列は、行が更新されると常に自動的に更新されます。そのため、特定の行が最後に更新された日時を追跡すると便利です。
詳細については、ブログ投稿Timestamp Vs Datetimeをご覧ください。
SET time_zone = '+0:00';
から取得/設定するTIMESTAMP
値を確認し、変更される可能性のあるサーバーのtime_zoneのデフォルトに依存しないようにするために、(ここではUTC )を使用して、常にセッションレベルでタイムゾーンを定義できます(推奨)。
私は常にUnixタイムスタンプを使用しています。これは、多くの日時情報を扱う場合、特にタイムゾーンの調整や日付の追加/減算などを行う場合に、正気を保つためです。タイムスタンプを比較する場合、これによりタイムゾーンの複雑な要素が除外され、サーバー側の処理(アプリケーションコードでもデータベースクエリでも)でリソースを節約できるため、より重い日付/時刻の加算/減算ではなく、軽量の計算を利用できます。機能。
考慮に値するもう1つのこと:
アプリケーションを構築している場合、データを将来どのように使用する必要があるかはわかりません。たとえば、データセット内の一連のレコードを、たとえば、サードパーティのAPIからの一連のアイテムと比較し、時系列順に並べる必要がある場合は、次のようになります。行のUnixタイムスタンプ。MySQLタイムスタンプを使用する場合でも、保険としてUnixタイムスタンプを保存してください。
私の場合、システム、データベースサーバーなど、可能な限りすべての時間帯としてUTCを設定しています。顧客が別のタイムゾーンを必要とする場合は、アプリでそれを構成します。
タイムスタンプには暗黙的にタイムゾーンが含まれるため、ほとんどの場合、日時フィールドではなくタイムスタンプを使用します。そのため、さまざまなタイムゾーンのユーザーからアプリにアクセスし、ローカルタイムゾーンの日付と時刻を表示したいとき、このフィールドタイプを使用すると、データが日時フィールドに保存されている場合よりも簡単に実行できます。 。
さらに、データベースを別のタイムゾーンのシステムに移行する場合は、タイムスタンプを使用する方が自信があります。シュマー時間の変化があり、1時間以下の精度が必要な2つの瞬間間の差を計算する場合に起こり得る問題は言うまでもありません。
要約すると、私はこのタイムスタンプの利点を評価します:
このすべての理由から、可能な場合はUTCおよびタイムスタンプフィールドを選択します。そして私は頭痛を避けます;)
warranties.expires_at
、今日のようなものはMySQLタイムスタンプにすることはできません。
テーブルでUPDATEステートメントを実行するときは、タイムスタンプの変更に注意してください。'Name'(varchar)、 'Age'(int)、 'Date_Added'(timestamp)の列を持つテーブルがあり、次のDMLステートメントを実行した場合
UPDATE table
SET age = 30
次に、 'Date_Added'列のすべての値が現在のタイムスタンプに変更されます。
ON UPDATE CURRENT_TIMESTAMP
主な違い:
TIMESTAMPは、レコードへの変更を追跡し、レコードが変更されるたびに更新するために使用されます。DATETIMEは、レコードの変更の影響を受けない特定の静的な値を格納するために使用されます。
TIMESTAMPは、異なるTIME ZONE関連の設定の影響も受けます。DATETIMEは定数です。
TIMESTAMPは、現在のタイムゾーンを内部的にUTCに変換して保存し、取得時に現在のタイムゾーンに変換し直しました。DATETIMEはこれを行うことができません。
TIMESTAMPでサポートされている範囲: '1970-01-01 00:00:01' UTCから '2038-01-19 03:14:07' UTC DATETIMEでサポートされている範囲: '1000-01-01 00:00:00'から '9999 -12-31 23:59:59 ′
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP | DATETIME |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
| TIMESTAMP requires 4 bytes. | DATETIME requires 8 bytes. |
| Timestamp is the number of seconds that have elapsed since January 1, 1970 00:00 UTC. | DATETIME is a text displays 'YYYY-MM-DD HH:MM:SS' format. |
| TIMESTAMP supported range: ‘1970-01-01 00:00:01′ UTC to ‘2038-01-19 03:14:07′ UTC. | DATETIME supported range: ‘1000-01-01 00:00:00′ to ‘9999-12-31 23:59:59′ |
| TIMESTAMP during retrieval converted back to the current time zone. | DATETIME can not do this. |
| TIMESTAMP is used mostly for metadata i.e. row created/modified and audit purpose. | DATETIME is used mostly for user-data. |
+---------------------------------------------------------------------------------------+--------------------------------------------------------------------------+
datetime
タイムゾーンに関連する多くの問題やバグに直面した後、アプリケーションでの使用をやめました。私見の使用timestamp
はdatetime
ほとんどの場合よりも優れていますます。
何時ですか?答えは「2019-02-05 21:18:30」のようなもので、別の部分が欠けているため、未完成、未定義の回答、どのタイムゾーンですか?ワシントン?モスクワ?北京?
タイムゾーンなしで日時を使用すると、アプリケーションは1つのタイムゾーンしか処理しませんが、タイムスタンプには次の利点があります datetime
異なるタイムゾーンで同じ正確な時点を表示あります。
使用を後悔しdatetime
、タイムスタンプにデータを保存したい場合があります。
クライアントが快適に過ごせるようにするには、計算を行わず、時間を意味のあるタイムゾーンに変換せずに、希望するタイムゾーンに基づいて時間を表示する必要があります。必要なのはタイムゾーンを変更することだけで、すべてのアプリケーションコードは同じになります。(実際には、アプリケーションの開始時に常にタイムゾーンを定義するか、PHPアプリケーションの場合はリクエスト処理を行う必要があります)
SET time_zone = '+2:00';
滞在する国を変更し、別のタイムゾーンでデータを見ながら(実際のデータを変更せずに)データを維持する作業を続けます。
datetime
=アプリケーションは1つのタイムゾーンをサポート(挿入と選択の両方)
timestamp
=アプリケーションは任意のタイムゾーンをサポート(挿入と選択の両方)
この回答は、タイムゾーンに関してタイムスタンプの柔軟性と使いやすさを強調するためのものであり、列のサイズや範囲、割合などの他の違いについては説明していません。
date
あり、他のフィールドtimestamp
が1つのテーブルで使用している場合はどうなりますか。フィルタリングされたデータがwhere
タイムゾーンの変更に準拠していないため、新しい問題が発生すると思います。
date
クエリを送信する前に列のタイムゾーンの問題を修正する必要があります。
Unixタイムスタンプが好きです。数値に変換して、その数値を気にするだけだからです。さらに、期間を加算/減算して取得します。その後、結果を任意の形式で日付に変換します。このコードは、ドキュメントのタイムスタンプと現在の時刻の間に経過した分数を調べます。
$date = $item['pubdate']; (etc ...)
$unix_now = time();
$result = strtotime($date, $unix_now);
$unix_diff_min = (($unix_now - $result) / 60);
$min = round($unix_diff_min);