Delphi
Delphiでは、日付(および時刻)を扱うためにTDateやTDateTime型を使います。TDateTimeFieldなどコンポーネントが日
付(時刻)を扱う場合には、ほとんどTDateTime型が使われます。TDate/TDateTime型はDouble型と同等であり、Delphi
2.0以降では1899年12月30日からの経過日数をあらわします(小数部は時刻をあらわします)。これはOLE互換の型(オートメーションなどで使わ
れる型)です。事実上制約はありません。
なお、Delphi 1.0では西暦1年1月1日からの経過日数をあらわします。このため、Delphi 1.0の日付をDelphi 2.0以降の日付にするためには693594を加算してください。
また、Delphi
1.0でStrToDateやStrToDateTime関数に西暦を2桁で与えた場合、上位2桁は19であるものとみなされます。これに対し、
Delphi
2.0では現在の西暦の上位2桁が省略されたものとみなされます。つまり、2000年以降にプログラムを実行した場合には、20xx年をあらわすことにな
ります。DBEditやDBGridのような日付を入力できるデータベース対応コントロールでは、内部でこれらの関数を呼び出しているため、同じ処理が実
行されます。
問題を完全に取り除く確実な方法は、年を4桁で入力することです。そうでなければ、2桁の年号が入力された場合に、必要に応じて2000年以降の年に変
換できるようプログラムコードを入力する必要があります。たとえば、以下の関数は1950年より前の日付(つまり2桁で50未満)に100年を加算しま
す。
function Modify2000(const Value : TDateTime): TDateTime;
var
Year, Month, Day : Word;
begin
Result := Value;
DecodeDate(Result, Year, Month, Day);
if Year < 1950 then
Result := EncodeDate(Year + 100, Month, Day);
end;
データベース対応コントロールに日付を入力する場合は、Tableコンポーネントで登録する前に呼び出されるイベント(BeforePostイベント)に対するイベントハンドラを定義します。
procedure TForm1.Table1BeforePost(DataSet: TDataSet);
var
TempDate: TDateTime;
begin
TempDate := Table1.FieldByName('date_field').AsDateTime;
TempDate := Modify2000(TempDate);
Table1.FieldByName('date_field').AsDateTime := TempDate;
end;
Delphi 4 では、関数 StrToDate および StrToDateTime
は、グローバル変数TwoDigitYearCenturyWindow により 2 桁の年数の解釈を制御できます。この変数は、2
桁の年数を現在の世紀に含まれる年号と見なすか、または次の世紀の年号と見なすかを決めるための基準となる年を保持します。
TwoDigitYearCenturyWindow が 0 より大きい場合、その値を現在の年から差し引いて「ピボット」を決めます。ピボット以降の年は現在の世紀になり、ピボットより前の年は次の世紀になります。以下の表に例を示します。
現在の年 |
TwoDigitYearCenturyWindow |
ピボット |
mm/dd/03 |
mm/dd/50 |
mm/dd/68 |
1998 |
0(デフォルト) |
1900 |
1903 |
1950 |
1968 |
2002 |
0(デフォルト) |
2000 |
2003 |
2050 |
2068 |
1998 |
50 |
1948 |
2003 |
1950 |
1968 |
2000 |
50 |
1950 |
2003 |
1950 |
1968 |
2002 |
50 |
1952 |
2003 |
2050 |
1968 |
2020 |
50 |
1970 |
2003 |
2050 |
2068 |
2020 |
10 |
2010 |
2103 |
2050 |
2068 |
TwoDigitYearCenturyWindow を使うと、データ入力の年数が 2 桁に固定されている古いプログラムを変更せずに 2000
年問題に対応することができ、アプリケーションの寿命を延ばすことができます。ただし、より好ましい対応は年数を4 桁で管理するようにすることです。
C++Builder、Borland C++、Turbo C++
C++ 処理系では、古典的な C ライブラリ関数で使われる UNIX 互換の形式、C++ クラスライブラリ、Windows API など、さまざまなスタイルで日付が扱われます。
TDate、TDateTime型
C++Builderでは、Delphiと同じく、日付(および時刻)を扱うためにTDateやTDateTime型を使います。データベース項目やコ
ンポーネントが日付をはじめ、ほとんどの動作は上記のDelphi
2.0以降の場合と同じです。C++Builderで、1950年より前の2桁の日付に100年を加算する例とテーブルを更新する際のイベントハンドラの
例を以下に示します。
TDateTime __fastcall Modify2000(TDateTime Value)
{
Word Year, Month, Day;
DecodeDate(Value, Year, Month, Day);
if (Year < 1950)
return EncodeDate(Word(Year + 100), Month, Day);
return Value;
}
void __fastcall TForm1::Table1BeforePost(TDataSet *DataSet)
{
TDateTime TempDate;
TempDate = Table1->FieldByName("date_field")->AsDateTime;
TempDate = Modify2000(TempDate);
Table1->FieldByName("date_field")->AsDateTime = TempDate;
}
time_t型
UNIX互換の時刻型です。1970年1月1日00:00:00(GMT、グリニッジ標準時)からの経過時間を秒単位であらわします。time_t型の
実体は32ビットの符号付整数型(long型)ですので、表現できるのは2038年1月19日3時14分7秒までです。この型を使う場合には、タイムゾー
ンによって値が変わることに注意してください。
date構造体、dosdate_t構造体
(16ビットの)システムが持つ日付情報を取得・設定するための構造体です。システム時刻は、1980年から2079年(※)までが有効です。
TDateクラス
Borland C++ 以前の C++
コンパイラにおいて提供される汎用クラスライブラリ(CLASSLIB)の日付クラスです(C++Builder の TDate
型とは互換性がありません)。1901年1月1日を基準(0)とする通算日数をもとにしています(1900以前は負の値として表現されます)。グレゴリオ
暦が始まった1752年9月14日より前では正しく動作しません。
なお、Borland C++ 5.02 ではグレゴリオ暦から対応するユリウス暦への変換に問題があります。この問題を回避するために、この date.cpp を使ってください。
double型
OLEオートメーションなどで日付・時刻を表現するために使われる型です。1899年12月30日からの経過日数をあらわします(小数部は時刻をあらわします)。1900年以降の日付を表現でき、事実上制約はありません。
unsigned short型
16ビットFATでファイルの更新日付を処理するために使われる型です。findfirstなどで使われるffblk構造体のメンバff_fdateの型です。ファイルの更新日付は、1980年から2099年(*1)までが有効です。
SYSTEMTIME構造体(Win32のみ)
(Win32環境で)Windows APIのGetLocalTimeなどで使われる日付・時刻をあらわす構造体です。表現できる日付・時刻の制約は、OSに依存します。
※注意 DOSのシステム日付やファイルシステムは、内部表現としては2107年までをカバーできます。しかし、DOSコマンドをはじめ利用環境によっては2079年(または2099年)までしか正しくサポートされない場合があります。
JBuilder
Javaでは、2000年問題を考慮した日付クラスが用いられています。JDK
1.1で追加されたjava.util.Calendarクラス、java.util.GregorianCalendarクラスを用いれば、紀元前を含
む4桁の西暦年号を保持することができます。
データベースに保管された日付データは、java.sql.Dateまたはjava.sql.Timestampクラスによって扱われます。これらのク
ラスは、java.util.Dateクラスをラップして、対応するデータベースのDATEまたはTIMESTAMP値を保持します。従って、これらの
データ型では、西暦から1900を引いた値によって年号が扱われます。もちろん、2000年以降の年号も扱うことができます。
西暦年号の表示形式
Javaでは、日付の書式化にjava.text.DateFormatクラスを用います。このクラスは、特定のロケール情報に基づいた日付の書式化機
能を提供します。このクラスのgetDateInstance()メソッドやgetDateTimeInstance()を用いると、指定したロケールや
デフォルトのロケールの日付時刻のフォーマッタを取得できます。
DataExpressによるデータベースデータの扱いでは、Variantクラスが使用されますが、内部的にはJavaが提供する各種データ型を用い
ています。DATE型やTIMESTAMP型の場合、書式化にはDateFormatクラスのフォーマッタを使用します。このとき、取得されるインスタン
スは、指定されたロケールです。通常ロケールはデフォルトに設定されており環境に依存しますが、特定のロケールをプロパティによって設定することもできま
す。データセットに適用されるロケールを設定するには、QueryDataSetのlocaleプロパティに特定のロケールを指定します。
4桁の西暦年号を明示的に表示する方法
DataExpressを用いてデータベースアクセスプログラムを作成したときに、明示的に4桁の西暦年号を表示させるには、Columnコンポーネン
トのdisplayMaskプロパティを設定して下さい。例えば、yyyy/MM/ddのようにdisplayMaskプロパティを設定すれば、1998
年2月3日は、次のように表示されます。
1998/02/03
editMaskプロパティを設定すれば、4桁の西暦を明示的に入力させることもできます。設定は、displayMaskと同様に、yyyy/MM/ddのように行います。
dBASE III PLUS 〜 Visual dBASE 5.5
dBASE III PLUS から Visual dBASE 5.5以前の、すべての dBASE では、日付項目は YYYYMMDD
という形式の文字列として保持されます。作成したアプリケーションが表示する年については、アプリケーション自身を修正することで対応でき、2
桁表示を自動的に 4 桁表示に変更する機能を追加する予定はありません。
Windows 版では、[デスクトッププロパティ]ダイアログの[国別情報]ページで[年を4桁で表示(C)]にチェックマークをつければ、以降の日付入力部分で年が4桁で表示/入力できるようになります。
また、dBASE III PLUS 以降では、21 世紀に対応するため SET CENTURY
コマンドを追加しています。プログラムかコマンドプロンプト(コマンドウィンドウの入力ペイン)で「SET CENTURY
ON」コマンドを使えば、年が 4 桁で表示/入力できるようになります。「SET CENTURY OFF」コマンドは、年を 2
桁で表示/入力するようにします。日付の計算は SET CENTURY コマンドに関わらず、正しく計算されます。SET CENTURY OFF
コマンドを使っていて、「STORE {01/01/2000} TO MYDATE」のようなコマンドで年が 00
と表示されている場合でも、ディスクやメモリ上には「20000101」と記録されています。YEAR 関数は、常に 4 桁の年を返します。
Visual dBASE 5.6 〜 Visual dBASE 7
Visual dBASE 5.6 では、SET EPOCH 文が追加されました。SET EPOCH は、日付にある 2
桁の年をどのように解釈するかを設定するものです。「SET EPOCH TO nnnn」という形式を使い、デフォルトでは 1900
を基準年としており、1900 〜 1999 をあらわします。SET EPOCH を使うと、SET CENTURY OFF
の状態で、世紀の境界にまたがる日付を 2 桁で入力できるようになります。
次の表では、異なる 3 つの SET EPOCH 設定により日付がどのように解釈されるかを示します。
基準年\例 |
5/5/00 |
5/5/30 |
5/5/99 |
|
1900 |
05/05/1900 |
05/05/1930 |
05/05/1999 |
1930 |
05/05/2000 |
05/05/1930 |
05/05/1999 |
2000 |
05/05/2000 |
05/05/2030 |
05/05/2099 |
たとえば、SET EPOCH を 1930 に設定すると、2 桁の年を変更しないまま大半のアプリケーションを 21
世紀でも使い続けることができます。ただし、この設定では 1930
年以前の日付を入力できなくなります。しかし、大半のアプリケーションにとってトラブルにはならないと思います。
しかし、アプリケーションが 100 年を超える範囲の日付を扱うときは、SET EPOCH だけでは不十分です。SET CENTURY を ON に設定し、西暦を明示的に 4 桁で入力する必要があります。
SET EPOCH で設定した基準年は、どんな日付の解釈にも適用されます。また、プログラム中の文字列にある 2
桁の日付はコンパイル時に評価されます。SET EPOCH
を使う際には、コンパイルされたコード、実行、修正の際に正しく設定されているかを確認してください。SET EPOCH
は、セッションベースのグローバルな設定です。SET EPOCH の値は、SET() や SETTO() 関数で取り出せます。
InterBase
InterBase はいつでも正確に日付データを解釈し保存します。InterBase は 2
桁の年号の日付データを保存する場合、入力されたデータが現在の日付と比べて 20 世紀と 21
世紀のどちらが近いかにより日付データを処理します。例えば、入力されたデータが 09/01/32 の場合、09/01/2032
として解釈します。これは現在の日付と比較した場合、2032 年の方が小さい差のためです。年号が 4
桁で入力された場合はこの解釈を行いません。また、いったん入力された 2 桁の年号の日付データは内部では 4 桁で保存されます。InterBase
は A.D. 100/01/01 から A.D. 32767/02/28 までの日付データをサポートします。
※注意 便宜上 1900 年代を 20 世紀、2000 年代を 21 世紀と表現していますが、正しくは 20 世紀は 1901〜2000年、21 世紀 は 2001〜2100 年です。
インプライズ製品情報 ページへ戻る
|