marunomaruno-memo

marunomaruno-memo

[Java] UTC 時間と SimpleDateFormat の不思議

2012年03月02日 | Java
[Java] UTC 時間と SimpleDateFormat の不思議
================================================================================

UTC 時間を表示するときに、SimpleDateFormat を使って表示すると、JST 時間で表示さ
れる。System.out.printf()で %tT とすると、ちゃん と UTC として表示される。なぜ?
オブジェクトは、ただしく UTC として作られている。

□ UTCSample.java
---
package jp.rutles.sample;

import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.TimeZone;

public class UTCSample {

    public static void main(String[] args) {
        SimpleDateFormat fmt =
                new SimpleDateFormat(
                    "yyyy 年 M 月 d 日 (E) HH:mm:ss");

        Calendar today = Calendar.getInstance();
        System.out.println(today);
        System.out.println(fmt.format(today.getTime()));
        System.out.printf("%1$tF %1$tT%n%n", today);

        TimeZone tz = TimeZone.getTimeZone("UTC");
        Calendar utc = Calendar.getInstance(tz);
        System.out.println(utc);
        System.out.println(fmt.format(utc.getTime()));
        System.out.printf("%1$tF %1$tT%n%n", utc);
    }

}
/* 実行結果
java.util.GregorianCalendar[time=1330561100890,areFieldsSet=true,areAllFieldsSet
=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Tokyo",offset=324000
00,dstSavings=0,useDaylight=false,transitions=10,lastRule=null],firstDayOfWeek=1,
minimalDaysInFirstWeek=1,ERA=1,YEAR=2012,MONTH=2,WEEK_OF_YEAR=9,WEEK_OF_MONTH=1,
DAY_OF_MONTH=1,DAY_OF_YEAR=61,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=
9,HOUR_OF_DAY=9,MINUTE=18,SECOND=20,MILLISECOND=890,ZONE_OFFSET=32400000,DST_OFF
SET=0]
2012 年 3 月 1 日 (木) 09:18:20
2012-03-01 09:18:20

java.util.GregorianCalendar[time=1330561100906,areFieldsSet=true,areAllFieldsSet
=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="UTC",offset=0,dstSavings=
0,useDaylight=false,transitions=0,lastRule=null],firstDayOfWeek=1,minimalDaysInF
irstWeek=1,ERA=1,YEAR=2012,MONTH=2,WEEK_OF_YEAR=9,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,
DAY_OF_YEAR=61,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=1,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,
MINUTE=18,SECOND=20,MILLISECOND=906,ZONE_OFFSET=0,DST_OFFSET=0]
2012 年 3 月 1 日 (木) 09:18:20
2012-03-01 00:18:20
*/
---

                                                                            以上



[Android] フォームの標準ウィジェット(2) 静的な選択関連 - 数値の指定

2012年03月01日 | Android
[Android] フォームの標準ウィジェット(2) 静的な選択関連 - 数値の指定
================================================================================

※ 前回、記事サイズの関係で紹介できなかったシークバーとレーティングバーについて紹介する。

選択する以下の ウィジェット(Widget)とそのイベント処理。
    ・ボタン(前回紹介)
    ・チェックボックス(前回紹介)
    ・トグルボタン(前回紹介)
    ・ラジオボタン(前回紹介)
    ・スピナー(前回紹介)
    ・シークバー
    ・レーティングバー

上記のウィジェットは、それぞれつぎのクラスを使う。また、そのときに使われるリス
ナー・インターフェースも示す。

------------------ -------------- ----------------------------------------------
ウィジェット       クラス         リスナー・インターフェース
------------------ -------------- ----------------------------------------------
ボタン             Button         View.OnClickListener, View.OnLongClickListener
                                  View.OnTouchListener
チェックボックス   CheckBox       CompoundButton.OnCheckedChangeListener
                                  View.OnClickListener, View.OnLongClickListener
                                  View.OnTouchListener
トグルボタン       ToggleButton   CompoundButton.OnCheckedChangeListener
                                  View.OnClickListener, View.OnLongClickListener
                                  View.OnTouchListener
ラジオボタン       RadioGroup     RadioGroup.OnCheckedChangeListener
                   RadioButton
スピナー           Spinner        AdapterView.OnItemSelectedListener
                                  View.OnTouchListener
シークバー         SeekBar        SeekBar.OnSeekBarChangeListener
                                  View.OnTouchListener
レーティングバー   RatingBar      RatingBar.OnRatingBarChangeListener
                                  View.OnTouchListener
------------------ -------------- ----------------------------------------------

このサンプルは、アプリケーションの起動時に選択する値が決まっているパターンを示す。


▲ レイアウト

□ res/layout/main.xml
---
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >

    <!-- (7) シークバー -->
    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="50" />

    <!-- (8) レーティングバー -->
    <RatingBar
        android:id="@+id/ratingBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:rating="2.5" />

</LinearLayout>
---

(7) シークバー

シークバーは、バー(スライダー)を指でタッチして、伸ばしたり縮めたりして、数値を設
定するウィジェット。EditText と違い、一定の範囲内で数値を設定できる。

    <SeekBar
        android:id="@+id/seekBar1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:max="100"
        android:progress="50" />

android:max        最大値
android:progress   初期状態での設定値


(8) レーティングバー

シークバーの一種で、5 段階評価のような感じの指定ができる。

    <RatingBar
        android:id="@+id/ratingBar1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:rating="2.5" />

android:rating    初期状態での設定値


▲リソース値

□ res/values/strings.xml
※ 前回と同じ


▲ アクティビティ

単に、Widget にあわせたリスナーを割り当てているだけである。
なお、リスナーはインナー・クラスを使っている。
どのハンドラーが使われたかは、トーストとログで表示している。

□ FormWidgets01Activity.java
package jp.marunomarun.android.formwidgets;

import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RatingBar;
import android.widget.SeekBar;
import android.widget.Spinner;
import android.widget.Toast;
import android.widget.ToggleButton;

public class FormWidgets01Activity extends Activity {
    private static final int TOAST_DURATION = Toast.LENGTH_SHORT;

    private Context context; // (1)

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        context = this; // (2)

        OnCheckAndLongClickListener clickListener = new OnCheckAndLongClickListener();
        OnTouchListener touchListener = new OnTouchListener();

        // シークバー
        SeekBar seekBar1 = (SeekBar) findViewById(R.id.seekBar1);
        seekBar1.setOnSeekBarChangeListener(new OnSeekBarListener());
        seekBar1.setOnClickListener(clickListener); // 動かないだけ
        seekBar1.setOnLongClickListener(clickListener); // 動かないだけ
        seekBar1.setOnTouchListener(touchListener);

        // レーティングバー
        RatingBar raitingBar1 = (RatingBar) findViewById(R.id.ratingBar1);
        raitingBar1.setOnRatingBarChangeListener(new OnRatingBarListener());
        raitingBar1.setOnClickListener(clickListener); // 動かないだけ
        raitingBar1.setOnLongClickListener(clickListener); // 動かないだけ
        raitingBar1.setOnTouchListener(touchListener);
    }

    /**
     * ボタンのクリック、長クリックに対するリスナー
     * 
     * @author marunomaruno
     */
    private class OnCheckAndLongClickListener implements View.OnClickListener,
            View.OnLongClickListener {

        @Override
        public void onClick(View v) {
            String message = String.format(
                    "OnClickListener.onClick() view: %s", v.getTag());
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
        }

        @Override
        public boolean onLongClick(View v) {
            String message = String.format(
                    "OnLongClickListener.onLongClick() view: %s", v.getTag());
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
            return false;
        }
    }

    /**
     * タッチに対するリスナー
     * 
     * @author marunomaruno
     */
    private class OnTouchListener implements View.OnTouchListener {

        @Override
        public boolean onTouch(View v, MotionEvent event) {
            String message = String.format(
                    "OnTouchListener.onTouch() view: %s, event: %s",
                    v.getTag(), event);
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
            return false;
        }
    }

    /**
     * シークバーの変更に対するリスナー
     * 
     * @author marunomaruno
     */
    private class OnSeekBarListener implements SeekBar.OnSeekBarChangeListener {

        @Override
        public void onProgressChanged(SeekBar seekBar, int progress,
                boolean fromUser) {
            String message = String
                    .format("OnSeekBarChangeListener.onProgressChanged() view: 
                                                    %s, value: %d, fromUser: %b",
                            seekBar.getTag(), progress, fromUser);
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
        }

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            String message = String
                    .format("OnSeekBarChangeListener.onStartTrackingTouch() view: 
                                                                %s, value: %d",
                            seekBar.getTag(), seekBar.getProgress());
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            String message = String
                    .format("OnSeekBarChangeListener.onStopTrackingTouch() view:
                                                                 %s, value: %d",
                            seekBar.getTag(), seekBar.getProgress());
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
        }
    }

    /**
     * レーティング・バーの変更に対するリスナー
     * 
     * @author marunomaruno
     */
    private class OnRatingBarListener implements
            RatingBar.OnRatingBarChangeListener {

        @Override
        public void onRatingChanged(RatingBar ratingBar, float rating,
                boolean fromUser) {
            String message = String.format(
                    "RatingBar onRatingChanged() rate: %f, fromUser: %b",
                    rating, fromUser);
            System.out.println(message);
            Toast.makeText(context, message, TOAST_DURATION).show();
        }
    }
}
---

(1)(2) コンテキスト・オブジェクト

内部クラスでトーストを使っているので、このアクティビティ自身(this オブジェクト)
を持っていたほうが都合がよい。

    private Context context;    // (1)
    context = this;    // (2)


(●) シークバー

シークバーは、バー(スライダー)を指でタッチして、伸ばしたり縮めたりして、数値を設
定するウィジェット。EditText と違い、一定の範囲内で数値を設定できる。

    SeekBar seekBar1 = (SeekBar) findViewById(R.id.seekBar1);
    seekBar1.setOnSeekBarChangeListener(new OnSeekBarListener());
    seekBar1.setOnClickListener(clickListener); // 動かないだけ
    seekBar1.setOnLongClickListener(clickListener); // 動かないだけ
    seekBar1.setOnTouchListener(touchListener);

なお、setOnClickListener()、setOnTouchListener() を指定しても動かない。


クリック時の動き
まとめると、ACTION_DOWN > onStartTrackingTouch > onProgressChanged > ACTION_UP >
                                                         onStopTrackingTouch
---
OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c41208 action=0 ...}
OnSeekBarChangeListener.onStartTrackingTouch() view: SeekBar, value: 50
OnSeekBarChangeListener.onProgressChanged() view: SeekBar, value: 86, fromUser: true
OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c41208 action=1 ...}
OnSeekBarChangeListener.onStopTrackingTouch() view: SeekBar, value: 86
---

長押し時の動き
まとめると、ACTION_DOWN > onStartTrackingTouch > ACTION_MOVE > onProgressChanged
                                             > ACTION_UP > onStopTrackingTouch
---
OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=0 ...}
OnSeekBarChangeListener.onStartTrackingTouch() view: SeekBar, value: 50
OnSeekBarChangeListener.onProgressChanged() view: SeekBar, value: 80, fromUser: true
OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=2 ...}
OnSeekBarChangeListener.onProgressChanged() view: SeekBar, value: 79, fromUser: true
OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=2 ...}
OnTouchListener.onTouch() view: SeekBar, event: MotionEvent{46c1fb60 action=1 ...}
OnSeekBarChangeListener.onStopTrackingTouch() view: SeekBar, value: 79
---


△ SeekBar クラス

java.lang.Object 
   +  android.view.View 
     +  android.widget.ProgressBar 
       +  android.widget.AbsSeekBar 
         +  android.widget.SeekBar 

シークバーを管理するクラス。
setMax() で最大値を指定しなければ、0 ~ 100 の範囲での指定になる。


・メソッド
---
void  setOnSeekBarChangeListener(SeekBar.OnSeekBarChangeListener l) 
synchronized void  setMax(int max)
synchronized int   getProgress()
synchronized void  setProgress(int progress)    
---


△ SeekBar.OnSeekBarChangeListener インターフェース

android.widget.SeekBar.OnSeekBarChangeListener

・メソッド
---
abstract void  onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) 
abstract void  onStartTrackingTouch(SeekBar seekBar) 
abstract void  onStopTrackingTouch(SeekBar seekBar)  
---


(●) レーティングバー

シークバーの一種で、5 段階評価のような感じの指定ができる。

    RatingBar raitingBar1 = (RatingBar) findViewById(R.id.ratingBar1);
    raitingBar1.setOnRatingBarChangeListener(new OnRatingBarListener());
    raitingBar1.setOnClickListener(clickListener); // 動かないだけ
    raitingBar1.setOnLongClickListener(clickListener); // 動かないだけ
    raitingBar1.setOnTouchListener(touchListener);


クック時の動き
まとめると、ACTION_DOWN > ACTION_UP > onRatingChanged
---
OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c41208 action=0 ...}
OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fc70 action=1 ...}
RatingBar onRatingChanged() rate: 5.000000, fromUser: true
---


長押し時の動き
まとめると、ACTION_DOWN > ACTION_MOVE > ACTION_UP > onClick
---
OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fb60 action=0 ...]
OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fb60 action=2 ...}
OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c1fb60 action=2 ...]
OnTouchListener.onTouch() view: RatingBar, event: MotionEvent{46c20bd0 action=1 ...]
RatingBar onRatingChanged() rate: 1.000000, fromUser: true
---


△ RatingBar クラス

java.lang.Object 
   +  android.view.View 
     +  android.widget.ProgressBar 
       +  android.widget.AbsSeekBar 
         +  android.widget.RatingBar 

レーティング・バーを管理するクラス。


・主なメソッド
---
int      getNumStars() 
float    getRating() 
float    getStepSize() 
boolean  isIndicator()  
void     setIsIndicator(boolean isIndicator) 
synchronized void  setMax(int max) 
void     setNumStars(int numStars) 
void     setOnRatingBarChangeListener(RatingBar.OnRatingBarChangeListener listener)
void     setRating(float rating) 
void     setStepSize(float stepSize)  
---


△ RatingBar.OnRatingBarChangeListener インターフェース

android.widget.RatingBar.OnRatingBarChangeListener

レーティング・バーが変化したときのリスナー・インターフェース。


・メソッド
---
abstract void  onRatingChanged(RatingBar ratingBar, float rating, boolean fromUser) 
---

                                                                            以上