001    /*
002     *  Copyright 2001-2005 Stephen Colebourne
003     *
004     *  Licensed under the Apache License, Version 2.0 (the "License");
005     *  you may not use this file except in compliance with the License.
006     *  You may obtain a copy of the License at
007     *
008     *      http://www.apache.org/licenses/LICENSE-2.0
009     *
010     *  Unless required by applicable law or agreed to in writing, software
011     *  distributed under the License is distributed on an "AS IS" BASIS,
012     *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     *  See the License for the specific language governing permissions and
014     *  limitations under the License.
015     */
016    package org.joda.time;
017    
018    import junit.framework.Assert;
019    import junit.framework.TestCase;
020    import junit.framework.TestSuite;
021    
022    import org.joda.time.format.DateTimeFormatter;
023    import org.joda.time.format.ISODateTimeFormat;
024    
025    /**
026     * Unit test the parsing of ISO format datetimes
027     *
028     * @author Guy Allard
029     * @author Stephen Colebourne
030     */
031    public class TestParseISO extends TestCase {
032        
033        private static final int DEFAULT = 99999;
034    
035        /**
036         * This is the main class for this test suite.
037         * @param args command line arguments.
038         */
039        public static void main(String[] args) {
040            junit.textui.TestRunner.run(suite());
041        }
042        
043        /**
044         * TestSuite suite() is a junit required method.
045         * @see org.joda.test.time.BulkTest
046         */
047        public static TestSuite suite() {
048            return new TestSuite(TestParseISO.class);
049        }
050        
051        /**
052         * Constructor.
053         * @param name
054         */
055        public TestParseISO(String name) {
056            super(name);
057        }
058    
059        protected void setUp() throws Exception {
060            super.setUp();
061        }
062        
063        protected void tearDown() throws Exception {
064            super.tearDown();
065        }
066        
067        //-----------------------------------------------------------------------
068        // Dates
069        //-----------------------------------------------------------------------
070        public void testSpecCompleteDate() {
071            new DMatcher("5.2.1.1", "1999-10-20", "19991020",
072                19, 99, 10, 20, DEFAULT).run();
073        }        
074        //-----------------------------------------------------------------------
075        public void testSpecReducedPrecisionCYM() {
076            new DMatcher("5.2.1.2", "1999-10", "199910",
077                19, 99, 10, DEFAULT, DEFAULT).run();
078        }
079        public void testSpecReducedPrecisionCY() {
080            new DMatcher("5.2.1.2", "1999", "1999",
081                19, 99, DEFAULT, DEFAULT, DEFAULT).run();
082        }
083        public void testSpecReducedPrecisionC() {
084            new DMatcher("5.2.1.2", "20", "20",
085                20, DEFAULT, DEFAULT, DEFAULT, DEFAULT).run();
086            new DMatcher("5.2.1.2", "19", "19",
087                19, DEFAULT, DEFAULT, DEFAULT, DEFAULT).run();
088        }
089        //-----------------------------------------------------------------------
090        public void testSpecTruncatedYMD() {
091            new DMatcher("5.2.1.3", "85-04-11", "850411",
092                DEFAULT, 85, 4, 11, DEFAULT).run();
093        }
094        public void testSpecTruncatedYM() {
095            new DMatcher("5.2.1.3", "-85-04", "-8504",
096                DEFAULT, 85, 4, DEFAULT, DEFAULT).run();
097        }
098        public void testSpecTruncatedY() {
099            new DMatcher("5.2.1.3", "-85", "-85",
100                DEFAULT, 85, DEFAULT, DEFAULT, DEFAULT).run();
101        }
102        public void testSpecTruncatedMD() {
103            new DMatcher("5.2.1.3", "--04-11", "--0411",
104                DEFAULT, DEFAULT, 4, 11, DEFAULT).run();
105        }
106        public void testSpecTruncatedM() {
107            new DMatcher("5.2.1.3", "--04", "--04",
108                DEFAULT, DEFAULT, 4, DEFAULT, DEFAULT).run();
109        }
110        public void testSpecTruncatedD() {
111            new DMatcher("5.2.1.3", "---11", "---11",
112                DEFAULT, DEFAULT, DEFAULT, 11, DEFAULT).run();
113        }
114        //-----------------------------------------------------------------------
115        public void testSpecExpandedCYMD() {
116            new DMatcher("5.2.1.4", "+001985-04-11", "+0019850411",
117                19, 85, 4, 11, DEFAULT).run();
118        }
119        public void testSpecExpandedCYM() {
120            new DMatcher("5.2.1.4", "+001985-04", "+00198504",
121                19, 85, 4, DEFAULT, DEFAULT).run();
122        }
123        public void testSpecExpandedCY() {
124            new DMatcher("5.2.1.4", "+001985", "+001985",
125                19, 85, DEFAULT, DEFAULT, DEFAULT).run();
126        }
127        public void testSpecExpandedC() {
128            // Not supported - could only tell difference from CY if you knew
129            // number of digits representing year
130    //        new DMatcher("5.2.1.4", "+0019", "+0019",
131    //            19, DEFAULT, DEFAULT, DEFAULT, DEFAULT).assert();
132        }
133        
134        //-----------------------------------------------------------------------
135        // Ordinal based date
136        //-----------------------------------------------------------------------
137        public void testSpecOrdinalComplete() {
138            new DMatcher("5.2.2.1", "1985-101", "1985101",
139                19, 85, 4, 11, DEFAULT).run();
140            new DMatcher("5.2.2.1", "1985-021", "1985021",
141                19, 85, 1, 21, DEFAULT).run();
142            new DMatcher("5.2.2.1", "1985-006", "1985006",
143                19, 85, 1, 6, DEFAULT).run();
144        }
145        //-----------------------------------------------------------------------
146        public void testSpecOrdinalTruncatedYD() {
147            new DMatcher("5.2.2.2", "85-101", "85101",
148                DEFAULT, 85, 4, 11, DEFAULT).run();
149        }
150        public void testSpecOrdinalTruncatedD() {
151            new DMatcher("5.2.2.2", "-101", "-101",
152                DEFAULT, DEFAULT, 4, 11, DEFAULT).run();
153        }
154        //-----------------------------------------------------------------------
155        public void testSpecOrdinalExpandedYD() {
156            new DMatcher("5.2.2.3", "+001985-101", "+001985101",
157                19, 85, 4, 11, DEFAULT).run();
158        }
159        //-----------------------------------------------------------------------
160        // Week based date
161        //-----------------------------------------------------------------------
162        public void testSpecWeekComplete() {
163            new DMatcher("5.2.3.1", "1985-W15-1", "1985W151",
164                19, 85, 4, 8, DEFAULT).run();
165            new DMatcher("5.2.3.1", "1985-W15-2", "1985W152",
166                19, 85, 4, 9, DEFAULT).run();
167            new DMatcher("5.2.3.1", "1985-W15-3", "1985W153",
168                19, 85, 4, 10, DEFAULT).run();
169            new DMatcher("5.2.3.1", "1985-W15-4", "1985W154",
170                19, 85, 4, 11, DEFAULT).run();
171            new DMatcher("5.2.3.1", "1985-W15-5", "1985W155",
172                19, 85, 4, 12, DEFAULT).run();
173            new DMatcher("5.2.3.1", "1985-W15-6", "1985W156",
174                19, 85, 4, 13, DEFAULT).run();
175            new DMatcher("5.2.3.1", "1985-W15-7", "1985W157",
176                19, 85, 4, 14, DEFAULT).run();
177        }
178        //-----------------------------------------------------------------------
179        public void testSpecWeekReducedPrecision() {
180            // test date is Sunday, which should be left alone
181            new DMatcher("5.2.3.2", "1985-W15", "1985W15",
182                19, 85, 4, 14, DEFAULT).run();
183        }
184        //-----------------------------------------------------------------------
185        public void testSpecWeekTruncatedYWD() {
186            new DMatcher("5.2.3.2", "85-W154", "85W154",
187                DEFAULT, 85, 4, 11, DEFAULT).run();
188        }
189        public void testSpecWeekTruncatedYW() {
190            // test date is Sunday, which should be left alone
191            new DMatcher("5.2.3.2", "85-W15", "85W15",
192                DEFAULT, 85, 4, 14, DEFAULT).run();
193        }
194        public void testSpecWeekTruncatedDWD() {
195            // decade not supported
196        }
197        public void testSpecWeekTruncatedDW() {
198            // decade not supported
199        }
200        public void testSpecWeekTruncatedWD() {
201            new DMatcher("5.2.3.2", "-W154", "-W154",
202                DEFAULT, DEFAULT, 4, 11, DEFAULT).run();
203        }
204        public void testSpecWeekTruncatedW() {
205            // test date is Sunday, which should be left alone
206            new DMatcher("5.2.3.2", "-W15", "-W15",
207                DEFAULT, DEFAULT, 4, 14, DEFAULT).run();
208        }
209        public void testSpecWeekTruncatedD() {
210            // test date is Sunday 3rd Dec, thus relative Thursday is 30th Nov
211            new DMatcher("5.2.3.3", "-W-4", "-W-4",
212                DEFAULT, DEFAULT, 11, 30, DEFAULT).run();
213        }
214        public void testSpecWeekExpandedYWD() {
215            // test date is Sunday 3rd Dec, thus relative Thursday is 30th Nov
216            new DMatcher("5.2.3.4", "+001985-W15-4", "+001985W154",
217                19, 85, 4, 11, DEFAULT).run();
218        }
219    
220        //-----------------------------------------------------------------------
221        // Times
222        //-----------------------------------------------------------------------
223        public void testSpecTimeComplete() {
224            new TMatcher("5.3.1.1", "23:20:50", "232050",
225                23, 20, 50, 0, DEFAULT).run();
226        }
227        //-----------------------------------------------------------------------
228        public void testSpecTimeReducedPrecisionHM() {
229            new TMatcher("5.3.1.2", "23:20", "2320",
230                23, 20, DEFAULT, DEFAULT, DEFAULT).run();
231        }
232        public void testSpecTimeReducedPrecisionH() {
233            new TMatcher("5.3.1.2", "23", "23",
234                23, DEFAULT, DEFAULT, DEFAULT, DEFAULT).run();
235        }
236        //-----------------------------------------------------------------------
237        public void testSpecTimeFractionalHMS() {
238            new TMatcher("5.3.1.3", "23:20:50.607", "232050.607",
239                23, 20, 50, 607, DEFAULT).run();
240            new TMatcher("5.3.1.3", "23:20:50,607", "232050,607",
241                23, 20, 50, 607, DEFAULT).run();
242        }
243        public void testSpecTimeFractionalHM() {
244            new TMatcher("5.3.1.3", "23:20.4", "2320.4",
245                23, 20, 24, 0, DEFAULT).run();
246            new TMatcher("5.3.1.3", "23:20,4", "2320,4",
247                23, 20, 24, 0, DEFAULT).run();
248        }
249        public void testSpecTimeFractionalH() {
250            new TMatcher("5.3.1.3", "23.25", "23.25",
251                23, 15, 0, 0, DEFAULT).run();
252            new TMatcher("5.3.1.3", "23.25", "23,25",
253                23, 15, 0, 0, DEFAULT).run();
254        }
255        //-----------------------------------------------------------------------
256        public void testSpecTimeTruncatedMS() {
257            new TMatcher("5.3.1.4", "-20:50", "-2050",
258                DEFAULT, 20, 50, 0, DEFAULT).run();
259        }
260        public void testSpecTimeTruncatedM() {
261            new TMatcher("5.3.1.4", "-20", "-20",
262                DEFAULT, 20, DEFAULT, DEFAULT, DEFAULT).run();
263        }
264        public void testSpecTimeTruncatedS() {
265            new TMatcher("5.3.1.4", "--50", "--50",
266                DEFAULT, DEFAULT, 50, 0, DEFAULT).run();
267        }
268        public void testSpecTimeTruncatedFractionMS() {
269            new TMatcher("5.3.1.4", "-20:50.607", "-2050.607",
270                DEFAULT, 20, 50, 607, DEFAULT).run();
271        }
272        public void testSpecTimeTruncatedFractionM() {
273            new TMatcher("5.3.1.4", "-20.4", "-20.4",
274                DEFAULT, 20, 24, 0, DEFAULT).run();
275        }
276        public void testSpecTimeTruncatedFractionS() {
277            new TMatcher("5.3.1.4", "--50.607", "--50.607",
278                DEFAULT, DEFAULT, 50, 607, DEFAULT).run();
279        }
280        
281        //-----------------------------------------------------------------------
282        //-----------------------------------------------------------------------
283        //-----------------------------------------------------------------------
284        /**
285         * Perform test.
286         */        
287        protected static abstract class Matcher extends Assert {
288            String spec, extended, basic;
289            int century, yearOfCentury, monthOfYear, dayOfMonth, hour, min, sec, milli, zone;
290            MutableDateTime dt;
291            
292            protected Matcher(String spec, String extended, String basic) {
293                this.spec = spec;
294                this.extended = extended;
295                this.basic = basic;
296            }
297            
298            protected abstract void run();
299            protected void assertDate() {
300                String msg = "\nSpec:   " + spec + "\nParsed: " + extended + "\nTo:     " + dt;
301                assertEquals(msg + "\nCentury: ", century, dt.getCenturyOfEra());
302                assertEquals(msg + "\nYear: ", yearOfCentury, dt.getYearOfCentury());
303                assertEquals(msg + "\nMonth: ", monthOfYear, dt.getMonthOfYear());
304                assertEquals(msg + "\nDay: ", dayOfMonth, dt.getDayOfMonth());
305                assertEquals(msg + "\nHour: ", hour, dt.getHourOfDay());
306                assertEquals(msg + "\nMinute: ", min, dt.getMinuteOfHour());
307                assertEquals(msg + "\nSecond: ", sec, dt.getSecondOfMinute());
308                assertEquals(msg + "\nMilli: ", milli, dt.getMillisOfSecond());
309                DateTimeZone z;
310                if (zone == DEFAULT) {
311                    z = DateTimeZone.getDefault();
312                } else if (zone == 0) {
313                        z = DateTimeZone.UTC;
314                } else {
315                    String str = "0" + Math.abs(zone) + ":00";
316                    str = str.substring(str.length() - 4);
317                    str = (zone < 0 ? "-" : "+") + str;
318                    z = DateTimeZone.forID(str);
319                }
320                assertEquals(msg + "\nZone: ", z, dt.getZone());
321            }
322            protected void parse(DateTimeFormatter p) {
323                int result = p.parseInto(dt, extended, 0);
324                assertTrue("\nSpec:   " + spec + "\nParsed: " + extended + "\nTo:     "
325                    + dt + "\nParse failed at: " + ~result,
326                    result >= 0);
327            }
328        }
329        protected static class DTMatcher extends Matcher {
330            protected DTMatcher(String spec, String extended, String basic,
331                    int century, int yearOfCentury, int monthOfYear, int dayOfMonth,
332                    int hour, int min, int sec, int milli, int zone) {
333                super(spec, extended, basic);
334                this.century = (century == DEFAULT ? 19 : century);
335                this.yearOfCentury = (yearOfCentury == DEFAULT ? 72 : yearOfCentury);
336                this.monthOfYear = (monthOfYear == DEFAULT ? 12 : monthOfYear);
337                this.dayOfMonth = (dayOfMonth == DEFAULT ? 3 : dayOfMonth);
338                this.hour = (hour == DEFAULT ? 10 : hour);
339                this.min = (min == DEFAULT ? 32 : min);
340                this.sec = (sec == DEFAULT ? 40 : sec);
341                this.milli = (milli == DEFAULT ? 205 : milli);
342                this.zone = zone;
343            }            
344            protected void run() {
345                dt = new MutableDateTime(1972, 12, 3, 10, 32, 40, 205);
346                parse(ISODateTimeFormat.dateTimeParser());
347                super.assertDate();
348            }
349        }
350        protected static class DMatcher extends Matcher {
351            protected DMatcher(String spec, String extended, String basic,
352                    int century, int yearOfCentury, int monthOfYear, int dayOfMonth, int zone) {
353                super(spec, extended, basic);
354                this.century = (century == DEFAULT ? 19 : century);
355                this.yearOfCentury = (yearOfCentury == DEFAULT ? 72 : yearOfCentury);
356                this.monthOfYear = (monthOfYear == DEFAULT ? 12 : monthOfYear);
357                this.dayOfMonth = (dayOfMonth == DEFAULT ? 3 : dayOfMonth);
358                this.hour = 10;
359                this.min = 32;
360                this.sec = 40;
361                this.milli = 205;
362                this.zone = zone;
363            }
364            protected void run() {
365                dt = new MutableDateTime(1972, 12, 3, 10, 32, 40, 205);
366                parse(ISODateTimeFormat.dateParser());
367                super.assertDate();
368            
369                dt = new MutableDateTime(1972, 12, 3, 10, 32, 40, 205);
370                parse(ISODateTimeFormat.dateTimeParser());
371                super.assertDate();
372            }
373        }
374        protected static class TMatcher extends Matcher {
375            protected TMatcher(String spec, String extended, String basic,
376                    int hour, int min, int sec, int milli, int zone) {
377                super(spec, extended, basic);
378                this.century = 19;
379                this.yearOfCentury = 72;
380                this.monthOfYear = 12;
381                this.dayOfMonth = 3;
382                this.hour = (hour == DEFAULT ? 10 : hour);
383                this.min = (min == DEFAULT ? 32 : min);
384                this.sec = (sec == DEFAULT ? 40 : sec);
385                this.milli = (milli == DEFAULT ? 205 : milli);
386                this.zone = zone;
387            }
388            protected void run() {
389                dt = new MutableDateTime(1972, 12, 3, 10, 32, 40, 205);
390                parse(ISODateTimeFormat.timeParser());
391                super.assertDate();
392                
393                extended = "T" + extended;
394                dt = new MutableDateTime(1972, 12, 3, 10, 32, 40, 205);
395                parse(ISODateTimeFormat.timeParser());
396                super.assertDate();
397                
398                dt = new MutableDateTime(1972, 12, 3, 10, 32, 40, 205);
399                parse(ISODateTimeFormat.dateTimeParser());
400                super.assertDate();
401            }
402        }
403    }