1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.joda.time.convert;
17
18 import org.joda.time.Chronology;
19 import org.joda.time.DateTime;
20 import org.joda.time.Period;
21 import org.joda.time.ReadWritableInterval;
22 import org.joda.time.ReadWritablePeriod;
23 import org.joda.time.ReadablePartial;
24 import org.joda.time.field.FieldUtils;
25 import org.joda.time.format.DateTimeFormatter;
26 import org.joda.time.format.ISODateTimeFormat;
27 import org.joda.time.format.ISOPeriodFormat;
28 import org.joda.time.format.PeriodFormatter;
29
30
31
32
33
34
35
36
37
38 class StringConverter extends AbstractConverter
39 implements InstantConverter, PartialConverter, DurationConverter, PeriodConverter, IntervalConverter {
40
41
42
43
44 static final StringConverter INSTANCE = new StringConverter();
45
46
47
48
49 protected StringConverter() {
50 super();
51 }
52
53
54
55
56
57
58
59
60
61
62 public long getInstantMillis(Object object, Chronology chrono) {
63 String str = (String) object;
64 DateTimeFormatter p = ISODateTimeFormat.dateTimeParser();
65 return p.withChronology(chrono).parseMillis(str);
66 }
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83 public int[] getPartialValues(ReadablePartial fieldSource, Object object, Chronology chrono, DateTimeFormatter parser) {
84 if (parser.getZone() != null) {
85 chrono = chrono.withZone(parser.getZone());
86 }
87 long millis = parser.withChronology(chrono).parseMillis((String) object);
88 return chrono.get(fieldSource, millis);
89 }
90
91
92
93
94
95
96
97
98
99 public long getDurationMillis(Object object) {
100
101
102 String original = (String) object;
103 String str = original;
104 int len = str.length();
105 if (len >= 4 &&
106 (str.charAt(0) == 'P' || str.charAt(0) == 'p') &&
107 (str.charAt(1) == 'T' || str.charAt(1) == 't') &&
108 (str.charAt(len - 1) == 'S' || str.charAt(len - 1) == 's')) {
109
110 } else {
111 throw new IllegalArgumentException("Invalid format: \"" + original + '"');
112 }
113 str = str.substring(2, len - 1);
114 int dot = -1;
115 boolean negative = false;
116 for (int i = 0; i < str.length(); i++) {
117 if (str.charAt(i) >= '0' && str.charAt(i) <= '9') {
118
119 } else if (i == 0 && str.charAt(0) == '-') {
120
121 negative = true;
122 } else if (i > (negative ? 1 : 0) && str.charAt(i) == '.' && dot == -1) {
123
124 dot = i;
125 } else {
126 throw new IllegalArgumentException("Invalid format: \"" + original + '"');
127 }
128 }
129 long millis = 0, seconds = 0;
130 int firstDigit = negative ? 1 : 0;
131 if (dot > 0) {
132 seconds = Long.parseLong(str.substring(firstDigit, dot));
133 str = str.substring(dot + 1);
134 if (str.length() != 3) {
135 str = (str + "000").substring(0, 3);
136 }
137 millis = Integer.parseInt(str);
138 } else if (negative) {
139 seconds = Long.parseLong(str.substring(firstDigit, str.length()));
140 } else {
141 seconds = Long.parseLong(str);
142 }
143 if (negative) {
144 return FieldUtils.safeAdd(FieldUtils.safeMultiply(-seconds, 1000), -millis);
145 } else {
146 return FieldUtils.safeAdd(FieldUtils.safeMultiply(seconds, 1000), millis);
147 }
148 }
149
150
151
152
153
154
155
156
157
158
159
160
161 public void setInto(ReadWritablePeriod period, Object object, Chronology chrono) {
162 String str = (String) object;
163 PeriodFormatter parser = ISOPeriodFormat.standard();
164 period.clear();
165 int pos = parser.parseInto(period, str, 0);
166 if (pos < str.length()) {
167 if (pos < 0) {
168
169 parser.withParseType(period.getPeriodType()).parseMutablePeriod(str);
170 }
171 throw new IllegalArgumentException("Invalid format: \"" + str + '"');
172 }
173 }
174
175
176
177
178
179
180
181
182
183 public void setInto(ReadWritableInterval writableInterval, Object object, Chronology chrono) {
184 String str = (String) object;
185
186 int separator = str.indexOf('/');
187 if (separator < 0) {
188 throw new IllegalArgumentException("Format requires a '/' separator: " + str);
189 }
190
191 String leftStr = str.substring(0, separator);
192 if (leftStr.length() <= 0) {
193 throw new IllegalArgumentException("Format invalid: " + str);
194 }
195 String rightStr = str.substring(separator + 1);
196 if (rightStr.length() <= 0) {
197 throw new IllegalArgumentException("Format invalid: " + str);
198 }
199
200 DateTimeFormatter dateTimeParser = ISODateTimeFormat.dateTimeParser();
201 dateTimeParser = dateTimeParser.withChronology(chrono);
202 PeriodFormatter periodParser = ISOPeriodFormat.standard();
203 long startInstant = 0, endInstant = 0;
204 Period period = null;
205 Chronology parsedChrono = null;
206
207
208 char c = leftStr.charAt(0);
209 if (c == 'P' || c == 'p') {
210 period = periodParser.withParseType(getPeriodType(leftStr)).parsePeriod(leftStr);
211 } else {
212 DateTime start = dateTimeParser.parseDateTime(leftStr);
213 startInstant = start.getMillis();
214 parsedChrono = start.getChronology();
215 }
216
217
218 c = rightStr.charAt(0);
219 if (c == 'P' || c == 'p') {
220 if (period != null) {
221 throw new IllegalArgumentException("Interval composed of two durations: " + str);
222 }
223 period = periodParser.withParseType(getPeriodType(rightStr)).parsePeriod(rightStr);
224 chrono = (chrono != null ? chrono : parsedChrono);
225 endInstant = chrono.add(period, startInstant, 1);
226 } else {
227 DateTime end = dateTimeParser.parseDateTime(rightStr);
228 endInstant = end.getMillis();
229 parsedChrono = (parsedChrono != null ? parsedChrono : end.getChronology());
230 chrono = (chrono != null ? chrono : parsedChrono);
231 if (period != null) {
232 startInstant = chrono.add(period, endInstant, -1);
233 }
234 }
235
236 writableInterval.setInterval(startInstant, endInstant);
237 writableInterval.setChronology(chrono);
238 }
239
240
241
242
243
244
245
246 public Class<?> getSupportedType() {
247 return String.class;
248 }
249
250 }