回答編集履歴

1

コメント追加、追記

2016/05/03 07:34

投稿

swordone
swordone

スコア20651

test CHANGED
@@ -20,11 +20,15 @@
20
20
 
21
21
  public static void main(String[] args) {
22
22
 
23
+
24
+
23
-
25
+ // 出力用フォーマット
24
26
 
25
27
  DateFormat forOut = new SimpleDateFormat("yyyy/MM/dd-HH:mm:ss");
26
28
 
29
+
30
+
27
-
31
+ // 段階的に解析するためのフォーマット
28
32
 
29
33
  SimpleDateFormat format1 = new SimpleDateFormat("yyyy/MM/dd");
30
34
 
@@ -34,11 +38,17 @@
34
38
 
35
39
  SimpleDateFormat format4 = new SimpleDateFormat(":ss");
36
40
 
41
+ SimpleDateFormat[] formats = { format1, format2, format3, format4 };
37
42
 
38
43
 
44
+
39
- SimpleDateFormat[] formats = { format1, format2, format3, format4 };
45
+ // 解析する情報に応じたCalendarクラスのフィールド定数
40
46
 
41
47
  int[] fields = { Calendar.DATE, Calendar.HOUR_OF_DAY, Calendar.MINUTE, Calendar.SECOND };
48
+
49
+
50
+
51
+ // 各種フォーマットを厳密モードにする
42
52
 
43
53
  for (SimpleDateFormat format : formats) {
44
54
 
@@ -50,29 +60,43 @@
50
60
 
51
61
  String[] times = { "2016/04/30", "2016/04/30-17", "2016/04/30-17:30", "2016/04/30-17:30:50",
52
62
 
53
- "2016/04/32", "2016/04/30-25", "2016/04/30-17:60", "2016/04/30-17:30:60"};
63
+ "2016/04/32", "2016/04/30-25", "2016/04/30-17:60", "2016/04/30-17:30:60", "2016-04-30"};
54
64
 
55
- for (String str : times) {
65
+ Text: for (String str : times) {
66
+
67
+ // 日時設定用Calendarインスタンス
56
68
 
57
69
  Calendar cal = Calendar.getInstance();
70
+
71
+ // 解析位置を保持するための、ParsePositionインスタンス
58
72
 
59
73
  ParsePosition pos = new ParsePosition(0);
60
74
 
61
75
 
62
76
 
77
+ // 解析位置が対象文字列の最後に達するか、formatsのフォーマットの数ループするまでループ
78
+
63
- for (int i = 0; i < formats.length; i++) {
79
+ for (int i = 0; pos.getIndex() < str.length() && i < formats.length; i++) {
64
80
 
65
81
  Date date = formats[i].parse(str, pos);
66
82
 
83
+ // 解析失敗時
84
+
67
85
  if (date == null) {
68
86
 
87
+ System.out.println(str + " の解析失敗 " + pos.getErrorIndex());
88
+
69
- break;
89
+ continue Text;
70
90
 
71
91
  }
92
+
93
+ // 最初の年月日はそのまま設定
72
94
 
73
95
  if (i == 0) {
74
96
 
75
97
  cal.setTime(date);
98
+
99
+ // 時分秒はDateをCalendarに変換し、対象のフィールドだけ抽出
76
100
 
77
101
  } else {
78
102
 
@@ -86,14 +110,6 @@
86
110
 
87
111
  }
88
112
 
89
- if (pos.getIndex() != str.length()) {
90
-
91
- System.out.println(str + " の解析失敗 " + pos.getIndex());
92
-
93
- continue;
94
-
95
- }
96
-
97
113
  System.out.println(str + " の解析結果 " + forOut.format(cal.getTime()));
98
114
 
99
115
  }
@@ -103,8 +119,6 @@
103
119
 
104
120
 
105
121
  }
106
-
107
-
108
122
 
109
123
  ```
110
124
 
@@ -131,3 +145,19 @@
131
145
  2016/04/30-17:60 の解析失敗 13
132
146
 
133
147
  2016/04/30-17:30:60 の解析失敗 16
148
+
149
+
150
+
151
+ ---
152
+
153
+
154
+
155
+ これで解析の可不可の判定、および解析した時のCalendarオブジェクトの取得が可能になります。
156
+
157
+ 開始、終了の時間の前後の判定はCalendarのcompareメソッドを使えば可能です。
158
+
159
+ また、エラーの内容として「書式が合っていない」か「存在しない日時」かを分けたければ、SimpleDateFormatを厳密モード、非厳密モードの2パターンで解析すれば可能かと思います。
160
+
161
+ 厳密で失敗し、非厳密で成功すれば「存在しない日時」、両方失敗すれば「書式が合っていない」とエラーが出せます。
162
+
163
+ ただし、このフォーマットだと"2016/4/30"の様に2桁であるべきところが1桁しかない場合も通すので、厳密に4桁/2桁/2桁などを判定したいのならやはり正規表現になるかもしれません。