Androidで日時を扱う

前置き

日時を処理するためのクラスについて整理します。

本文

日時を表現するクラス

java.util.Date

これは、タイムゾーンに依存しない絶対的な日時情報です。この情報にタイムゾーン情報を加えると、具体的な日時の値(2012-01-13 18:05:21など)が決まります。

  • ミリ秒の桁まで管理
  • 年や分など、各桁の値を取り出したり組み合わせる機能は無い(deprecated)

java.util.Calendar

  • java.util.Dateを内包
  • タイムゾーンとロケール情報も管理しており、年や分など、各桁の値を取り出したり組み合わせる機能を提供
  • 抽象クラス
  • getInstance()で具象クラスを得る →(たぶん)GregorianCalendar

現在日時を得る

Date now = new Date();

Dateオブジェクトから、各桁の値(つまり年、月、日、時、分、秒、ミリ秒)を得る

int getYear(Date d) {
  Calendar cal = Calendar.getInstance();
        // タイムゾーンとロケールは、システムデフォルト。
        // Calendar.getInstance(TimeZone, Locale)で明示も可能。
  cal.setTime(d);
  return cal.get(Calendar.YEAR);
        // calのタイムゾーンに応じた、年の値を得る。
}

日時のシリアライズ

Dateの情報は、long値としてシリアライズ可能です。

long toLong(Date d) {
  return d.getTime();
}

Date fromLong(long v) {
  return new Date(v);
}

void setLong(Date d, long v) {
  d.setTime(v);
}

このlong値は、GMTの1970-01-01 00:00:00.000からの積算ミリ秒になっています。Javaのlongは8バイト値なので、2038年問題の心配は不要です。

日時の比較

void compare(Date left, Date right) {
  if ( left.after(right) ) Log.d("", "left is after right.");
  if ( left.before(right) ) Log.d("", "left is before right.");
  if ( left.equals(right) ) Log.d("", "left is equal to right.");

  int i = left.compareTo(right);
  if ( i > 0 ) Log.d("", "left is after right.");
  if ( i < 0 ) Log.d("", "left is before right.");
  if ( i == 0 ) Log.d("", "left is equal to right.");
}

日時を指定して、Dateオブジェクトを作る

Date getDate(int y, int mo, int d, int h, int mi, int s, int ms) {
  Calendar cal = Calendar.getInstance();
        // タイムゾーンとロケールは、システムデフォルト。
        // Calendar.getInstance(TimeZone, Locale)で明示も可能。
  cal.set(y, mo, d, h, mi, s);
        // y, mo, d, h, mi, sを、
        // calのタイムゾーンにおける年月日時分秒と解釈して、
        // 内部のDateオブジェクトを変更。
  cal.set(Calendar.MILLISECOND, ms);
        // ミリ秒だけ変更。
  return cal.getTime();
        // Dateオブジェクトを取り出した時点で、
        // タイムゾーン情報は消える。
}

日時を文字列化する

android.text.format.DateFormatを使います。

String toString(Date d) {
  return DateFormat.format("yyyy-MM-dd(E)", d).toString();
        // デフォルトのタイムゾーンとロケールに応じて、日時を文字列化。
        // フォーマット文字列の仕様はjava.text.SimpleDateFormatを参照。
}

java.textパッケージにもDateFormat系列のクラスSimpleDateFormatがありますが、こちらは、コンストラクト時にフォーマット文字列を指定するスタイルです。

DateFormat#format()やSimpleDateFormatで使うフォーマット文字は、下記のような感じです。

  • yが年、Mが月、dが日
  • 例えば月なら、Mが1桁、MMが2桁、MMMが月名の短縮形、MMMMが非短縮形
  • Kは12時間制の時(0-11)、Hは24時間制(0-23)。1オリジンのh(1-12)とk(1-24)もある
  • mが分、sは秒で、Sがミリ秒
  • Eは曜日の短縮形で、EEEEは非短縮形
  • aaは午後か午前か
  • エスケープするには'で囲む

文字列をパースしてDateオブジェクトを作る

Date fromString(String ds) {
  SimpleDateFormat f = new SimpleDateFormat("yyyy-MM-dd");
  try {
    return f.parse(ds);
  } catch ( ParseException ex ) {
    throw new RuntimeException("a bad date string: " + ds);
  }
}

画面から日時を入力する

日付なら、android.app.DatePickerDialogクラスを使います。

  • タイムゾーンは無頓着
  • リスナDatePickerDialog.OnDateSetListenerが必要

Activity#onCreateDialog()で、ダイアログを生成します。

@Override
protected Dialog onCreateDialog(int id) {
  return new DatePickerDialog(this, this, 2012, 1, 13);
        // Context、OnDateSetListener、及び、初期値として使用する日付を指定。
}

日付の初期値は、onPrepareDialog()の中でセットしてもOKです。その場合は、DatePickerDialog#updateDate()を使います。

OKボタンがタッチされると、OnDateSetListener#onDateSet()がコールバックされます。

public void onDateSet(DatePicker view, int year, int monthOfYear, int dayOfMonth) {
  Calendar cal = Calendar.getInstance();
  cal.set(year, monthOfYear, dayOfMonth, 0, 0, 0);
  cal.set(Calendar.MILLISECOND, 0);
  Date pickedDate = cal.getTime();
}

同様に、時刻ならandroid.app.TimePickerDialogとOnTimeSetListenerです。

タイムゾーンを調べる

java.util.TimeZoneを使います。

TimeZone tz = TimeZone.getDefault();
int off = tz.getRawOffset();    // JSTなら9 * 60 * 60 * 1000。
Last modified:2012/05/11 14:35:57
Keyword(s):
References:[Androidアプリ開発]
This page is frozen.