├── docs ├── javadoc │ ├── package-list │ ├── resources │ │ ├── tab.gif │ │ ├── titlebar.gif │ │ ├── background.gif │ │ └── titlebar_end.gif │ ├── allclasses-noframe.html │ ├── allclasses-frame.html │ ├── index.html │ ├── hirondelle │ │ └── date4j │ │ │ ├── package-frame.html │ │ │ ├── doc-files │ │ │ └── VersionHistory.html │ │ │ ├── package-summary.html │ │ │ ├── package-tree.html │ │ │ └── DateTime.Unit.html │ ├── highlight.css │ ├── src-html │ │ └── hirondelle │ │ │ └── date4j │ │ │ ├── TESTAll.html │ │ │ ├── Util.html │ │ │ ├── Examples.html │ │ │ └── DateTimeParser.html │ ├── deprecated-list.html │ ├── constant-values.html │ ├── overview-summary.html │ ├── overview-tree.html │ ├── help-doc.html │ └── serialized-form.html ├── date4j.jar ├── date4j-source.zip ├── images │ └── favicon.ico ├── LICENSE_BSD.txt ├── highlight.css ├── web4j-javadoc.css ├── css │ └── stylesheet11.css └── examples.txt ├── libs └── junit.jar ├── .gitignore ├── MANIFEST.MF ├── CONTRIBUTING.txt ├── classes ├── hirondelle │ └── date4j │ │ ├── TESTAll.java │ │ ├── Util.java │ │ ├── doc-files │ │ └── VersionHistory.html │ │ ├── DateTimeParser.java │ │ ├── Examples.java │ │ ├── DateTimeInterval.java │ │ ├── TESTDateTimeFormatter.java │ │ └── ToStringUtil.java └── overview.html ├── README.md ├── LICENSE.txt ├── highlight.css └── javadoc.css /docs/javadoc/package-list: -------------------------------------------------------------------------------- 1 | hirondelle.date4j 2 | -------------------------------------------------------------------------------- /docs/date4j.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/date4j.jar -------------------------------------------------------------------------------- /libs/junit.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/libs/junit.jar -------------------------------------------------------------------------------- /docs/date4j-source.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/date4j-source.zip -------------------------------------------------------------------------------- /docs/images/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/images/favicon.ico -------------------------------------------------------------------------------- /docs/javadoc/resources/tab.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/javadoc/resources/tab.gif -------------------------------------------------------------------------------- /docs/javadoc/resources/titlebar.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/javadoc/resources/titlebar.gif -------------------------------------------------------------------------------- /docs/javadoc/resources/background.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/javadoc/resources/background.gif -------------------------------------------------------------------------------- /docs/javadoc/resources/titlebar_end.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johanley/date4j/HEAD/docs/javadoc/resources/titlebar_end.gif -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Please edit this file to suit your taste 2 | 3 | # Eclipse items 4 | .project 5 | .classpath 6 | .settings/ 7 | bin/ 8 | 9 | # generated binary files 10 | *.class 11 | 12 | # OS Files # 13 | .DS_Store 14 | 15 | # non-public items used by the project owner 16 | private.build.xml 17 | classes/javadocoptions.txt 18 | classes/classes.txt 19 | inherit.gif -------------------------------------------------------------------------------- /MANIFEST.MF: -------------------------------------------------------------------------------- 1 | Manifest-Version: 1.0 2 | Ant-Version: Apache Ant 1.6.5 3 | Created-By: 1.5.0_07-b03 (Sun Microsystems Inc.) 4 | Specification-Title: DATE4J 5 | Specification-Version: 1.5.2 6 | Specification-Vendor: Hirondelle Systems 7 | Implementation-Title: DATE4J 8 | Implementation-Version: 1.5.2 9 | Implementation-Vendor: Hirondelle Systems 10 | Implementation-URL: http://www.date4j.net/ 11 | 12 | -------------------------------------------------------------------------------- /CONTRIBUTING.txt: -------------------------------------------------------------------------------- 1 | Must compile with JDK 1.5. (This is important for remaining compatible 2 | with Android.) 3 | 4 | No tabs please. 5 | 6 | UTF-8 is the preferred file encoding. 7 | 8 | Braces like this please { 9 | //indent 2-3 spaces 10 | } 11 | 12 | The project includes junit.jar, version 3.8.1. 13 | That version is a bit stale, but for the sake of uniformity, please 14 | use that version of junit for any new tests, if you create any. 15 | -------------------------------------------------------------------------------- /classes/hirondelle/date4j/TESTAll.java: -------------------------------------------------------------------------------- 1 | package hirondelle.date4j; 2 | 3 | import junit.framework.Test; 4 | import junit.framework.TestSuite; 5 | 6 | /** Run all JUnit tests. */ 7 | public final class TESTAll { 8 | 9 | public static void main(String args[]) { 10 | String[] testCaseName = { TESTAll.class.getName()}; 11 | junit.textui.TestRunner.main(testCaseName); 12 | } 13 | 14 | public static Test suite ( ) { 15 | TestSuite suite= new TestSuite("All JUnit Tests"); 16 | 17 | suite.addTest(new TestSuite(TESTDateTime.class)); 18 | suite.addTest(new TestSuite(TESTDateTimeFormatter.class)); 19 | suite.addTest(new TestSuite(TESTDateTimeInterval.class)); 20 | 21 | return suite; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /classes/overview.html: -------------------------------------------------------------------------------- 1 | 2 | 3 |
4 | 5 | 6 | 7 |Version History 19 | 20 |
DATE4J is open source software. It's released under a BSD license. 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Date4j is a lightweight replacement for Java's built-in date classes. 2 | 3 | * compiles with JDK 1.5 or greater 4 | * can be used in Android projects 5 | * its public API is essentially a single class (DateTime) 6 | * BSD License 7 | 8 | In 2014, improved date classes were finally added to the JDK. 9 | Those classes render date4j more or less obsolete. 10 | 11 | Documentation is here (the site date4j.net has been shut down): 12 | 13 | https://johanley.github.io/date4j/index.html 14 | 15 | There's still a use case in which date4j is a good resource. 16 | When new languages are created, they all need a way to represent dates and times. 17 | As a starting point, one option is to port date4j to the new language. 18 | Since date4j consists essentially of a single class, this will not be 19 | be an excessively onerous task. 20 | 21 | Date4j contributors: 22 | 23 | * John O'Hanley (main author, Canada) 24 | * Piero Campalani (Italy) 25 | * Jean-Christophe Garnier (CERN - Switzerland) 26 | * Jamie Craane (Netherlands) 27 | * Dan J (USA) 28 | -------------------------------------------------------------------------------- /docs/javadoc/allclasses-noframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 |
5 | 6 || DateTime
24 | 25 | DateTime.DayOverflow 26 | 27 | DateTime.Unit 28 | 29 | |
30 |
| DateTime
24 | 25 | DateTime.DayOverflow 26 | 27 | DateTime.Unit 28 | 29 | |
30 |
|
23 | Classes
24 |
25 | 26 | DateTime |
27 |
|
34 | Enums
35 |
36 | 37 | DateTime.DayOverflow 38 | 39 | DateTime.Unit |
40 |
10 | package hirondelle.date4j; 11 | 12 | import junit.framework.Test; 13 | import junit.framework.TestSuite; 14 | 15 | /** Run all JUnit tests. */ 16 | public final class TESTAll { 17 | 18 | public static void main(String args[]) { 19 | String[] testCaseName = { TESTAll.class.getName()}; 20 | junit.textui.TestRunner.main(testCaseName); 21 | } 22 | 23 | public static Test suite ( ) { 24 | TestSuite suite= new TestSuite("All JUnit Tests"); 25 | 26 | suite.addTest(new TestSuite(TESTDateTime.class)); 27 | suite.addTest(new TestSuite(TESTDateTimeFormatter.class)); 28 | suite.addTest(new TestSuite(TESTDateTimeInterval.class)); 29 | 30 | return suite; 31 | } 32 | } 33 | 34 |35 | 36 | 37 | -------------------------------------------------------------------------------- /javadoc.css: -------------------------------------------------------------------------------- 1 | /* Javadoc style sheet */ 2 | .highlight { 3 | background-color: #FFFDE3; 4 | } 5 | 6 | /* syntax highlighting */ 7 | .keyword { 8 | font-weight: bolder; 9 | color: #000080; 10 | } 11 | .literal { 12 | color: blue; 13 | } 14 | .comment { 15 | color: green; 16 | } 17 | 18 | /* Define colors, fonts and other style attributes here to override the defaults */ 19 | 20 | /* Page background color */ 21 | /* body { background-color: #FFFFFF } */ 22 | body { 23 | background-color: rgb(90%, 90%, 90%); 24 | font-family: Verdana, sans-serif; 25 | } 26 | 27 | /*style of bullets. */ 28 | li { 29 | list-style-type: square; 30 | } 31 | 32 | .opening-quote{ 33 | margin: 10px; 34 | margin-left: 12.0em; 35 | margin-right: 10px; 36 | margin-top: 10px; 37 | margin-bottom: 10px; 38 | /* background-color:#E5E2D5; */ 39 | border-top: 1px solid #C2BB9E; 40 | border-left: 5px solid #C2BB9E; 41 | border-right: 5px solid #C2BB9E; 42 | border-bottom: 1px solid #C2BB9E; 43 | padding: 10px; 44 | width: 60%; 45 | } 46 | 47 | .author { 48 | font-style: italic; 49 | padding-top: 0em; 50 | margin-top: 0.25em; 51 | text-align: right; 52 | } 53 | 54 | /* Table colors */ 55 | .TableHeadingColor { background: #CCCCFF } /* Dark mauve */ 56 | .TableSubHeadingColor { background: #EEEEFF } /* Light mauve */ 57 | .TableRowColor { 58 | background-color: rgb(90%, 90%, 90%); 59 | /* background: #FFFFFF */ 60 | } 61 | 62 | /* Font used in left-hand frame lists */ 63 | .FrameTitleFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif } 64 | .FrameHeadingFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif } 65 | .FrameItemFont { font-size: 10pts; font-family: Helvetica, Arial, san-serif } 66 | 67 | /* Example of smaller, sans-serif font in frames */ 68 | /* .FrameItemFont { font-size: 10pt; font-family: Helvetica, Arial, sans-serif } */ 69 | 70 | /* Navigation bar fonts and colors */ 71 | .NavBarCell1 { background-color:#EEEEFF;}/* Light mauve */ 72 | .NavBarCell1Rev { background-color:#00008B;}/* Dark Blue */ 73 | .NavBarFont1 { font-family: Arial, Helvetica, sans-serif; color:#000000;} 74 | .NavBarFont1Rev { font-family: Arial, Helvetica, sans-serif; color:#FFFFFF;} 75 | 76 | .NavBarCell2 { font-family: Arial, Helvetica, sans-serif; background-color: rgb(90%, 90%, 90%);} 77 | .NavBarCell3 { font-family: Arial, Helvetica, sans-serif; background-color: rgb(90%, 90%, 90%);} 78 | 79 | -------------------------------------------------------------------------------- /classes/hirondelle/date4j/doc-files/VersionHistory.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 |
Thanks to Jean-Christophe Garnier for his assistance with this release. 32 | 33 |
Three methods have been added in this release. 34 |
public static boolean isParseable(String aCandidateDateTime)
36 | The remaining two methods form a pair, and let you pass nanosecond values into and out of DateTime: 40 |
public static DateTime forInstantNanos(long aNanoseconds, TimeZone aTimeZone)
42 | public long getNanosecondsInstant(TimeZone aTimeZone)
43 | Thanks to Piero Campalani for his help with this item. 54 | 55 |
59 | 2012-05-24T02:03:04 60 | 2012-05-24T02:03:04.123456789 61 |62 | This change is backwards-compatible. This change was added mainly for compatibility with the input type='datetime-local' 63 | defined by HTML5. It allows browser implementations to submit text of the above syntax. 64 | 65 |
Formatting
69 | The format() methods have changed implementation.
70 | The style 'YYYYMMDD', for example, is now permitted. (This corrects an oversight.)
71 |
72 |
In addition, the text that can be passed to the format methods can now take a much wider range of values. 73 | For example, a valid format String is : 74 |
'Now: YYYY-MM-DD hh:mm:ss'75 | This text acts like a little template. The preamble 'Now :' is simply echoed, since it contains no formatting symbols. 76 | 77 |
Such free-form text will often need pairs of escape characters '|', to prevent h, m, s, a, f, and so on from being interpreted 78 | as formatting symbols. For example : 79 |
'|The date is:| YYYY-MM-DD'80 | 81 |
DateTime.isValidFormatString(String)
82 | This method has been removed. Since the String passed to the format() methods has no restrictions, such a
83 | method no longer makes sense.
84 |
85 |
Thanks to Jean-Christophe Garnier for his assistance with this release. 32 | 33 |
Three methods have been added in this release. 34 |
public static boolean isParseable(String aCandidateDateTime)
36 | The remaining two methods form a pair, and let you pass nanosecond values into and out of DateTime: 40 |
public static DateTime forInstantNanos(long aNanoseconds, TimeZone aTimeZone)
42 | public long getNanosecondsInstant(TimeZone aTimeZone)
43 | Thanks to Piero Campalani for his help with this item. 54 | 55 |
59 | 2012-05-24T02:03:04 60 | 2012-05-24T02:03:04.123456789 61 |62 | This change is backwards-compatible. This change was added mainly for compatibility with the input type='datetime-local' 63 | defined by HTML5. It allows browser implementations to submit text of the above syntax. 64 | 65 |
Formatting
69 | The format() methods have changed implementation.
70 | The style 'YYYYMMDD', for example, is now permitted. (This corrects an oversight.)
71 |
72 |
In addition, the text that can be passed to the format methods can now take a much wider range of values. 73 | For example, a valid format String is : 74 |
'Now: YYYY-MM-DD hh:mm:ss'75 | This text acts like a little template. The preamble 'Now :' is simply echoed, since it contains no formatting symbols. 76 | 77 |
Such free-form text will often need pairs of escape characters '|', to prevent h, m, s, a, f, and so on from being interpreted 78 | as formatting symbols. For example : 79 |
'|The date is:| YYYY-MM-DD'80 | 81 |
DateTime.isValidFormatString(String)
82 | This method has been removed. Since the String passed to the format() methods has no restrictions, such a
83 | method no longer makes sense.
84 |
85 |
10 | package hirondelle.date4j; 11 | 12 | import java.lang.reflect.Array; 13 | import java.util.logging.Logger; 14 | 15 | final class Util { 16 | 17 | static boolean textHasContent(String aText) { 18 | return (aText != null) && (aText.trim().length() > 0); 19 | } 20 | 21 | static String quote(Object aObject){ 22 | return SINGLE_QUOTE + String.valueOf(aObject) + SINGLE_QUOTE; 23 | } 24 | 25 | static String getArrayAsString(Object aArray){ 26 | final String fSTART_CHAR = "["; 27 | final String fEND_CHAR = "]"; 28 | final String fSEPARATOR = ", "; 29 | final String fNULL = "null"; 30 | 31 | if ( aArray == null ) return fNULL; 32 | checkObjectIsArray(aArray); 33 | 34 | StringBuilder result = new StringBuilder( fSTART_CHAR ); 35 | int length = Array.getLength(aArray); 36 | for ( int idx = 0 ; idx < length ; ++idx ) { 37 | Object item = Array.get(aArray, idx); 38 | if ( isNonNullArray(item) ){ 39 | //recursive call! 40 | result.append( getArrayAsString(item) ); 41 | } 42 | else{ 43 | result.append( item ); 44 | } 45 | if ( ! isLastItem(idx, length) ) { 46 | result.append(fSEPARATOR); 47 | } 48 | } 49 | result.append(fEND_CHAR); 50 | return result.toString(); 51 | } 52 | 53 | static Logger getLogger(Class<?> aClass){ 54 | return Logger.getLogger(aClass.getPackage().getName()); 55 | } 56 | 57 | // PRIVATE 58 | 59 | private static final String SINGLE_QUOTE = "'"; 60 | 61 | private static boolean isNonNullArray(Object aItem){ 62 | return aItem != null && aItem.getClass().isArray(); 63 | } 64 | 65 | private static void checkObjectIsArray(Object aArray){ 66 | if ( ! aArray.getClass().isArray() ) { 67 | throw new IllegalArgumentException("Object is not an array."); 68 | } 69 | } 70 | 71 | private static boolean isLastItem(int aIdx, int aLength){ 72 | return (aIdx == aLength - 1); 73 | } 74 | 75 | } 76 | 77 |78 | 79 | 80 | -------------------------------------------------------------------------------- /docs/javadoc/deprecated-list.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
33 |
34 |
|
46 | 47 | Version 1.5.1 48 | | 49 |||||||||
| 53 | PREV 54 | NEXT | 55 |56 | FRAMES 57 | NO FRAMES 58 | 65 | 68 | 69 | 70 | | 71 |||||||||
94 |
95 |
|
107 | 108 | Version 1.5.1 109 | | 110 |||||||||
| 114 | PREV 115 | NEXT | 116 |117 | FRAMES 118 | NO FRAMES 119 | 126 | 129 | 130 | 131 | | 132 |||||||||
33 |
34 |
|
46 | 47 | Version 1.5.1 48 | | 49 |||||||||
| 53 | PREV 54 | NEXT | 55 |56 | FRAMES 57 | NO FRAMES 58 | 65 | 68 | 69 | 70 | | 71 |||||||||
94 |
95 |
|
107 | 108 | Version 1.5.1 109 | | 110 |||||||||
| 114 | PREV 115 | NEXT | 116 |117 | FRAMES 118 | NO FRAMES 119 | 126 | 129 | 130 | 131 | | 132 |||||||||
34 |
35 |
|
47 | 48 | Version 1.5.1 49 | | 50 |||||||||
| 54 | PREV 55 | NEXT | 56 |57 | FRAMES 58 | NO FRAMES 59 | 66 | 69 | 70 | 71 | | 72 |||||||||
80 | See:
81 |
82 | Description
83 |
84 | 85 |
| 88 | Packages | 89 ||
|---|---|
| hirondelle.date4j | 92 |93 | |
99 | DATE4J is a simple alternative to the standard JDK date classes. 100 | It was created by Hirondelle Systems (John O'Hanley). 101 | 102 |
Version History 108 | 109 |
DATE4J is open source software. It's released under a BSD license. 110 |
111 | 112 |
113 |
122 |
123 |
|
135 | 136 | Version 1.5.1 137 | | 138 |||||||||
| 142 | PREV 143 | NEXT | 144 |145 | FRAMES 146 | NO FRAMES 147 | 154 | 157 | 158 | 159 | | 160 |||||||||
34 |
35 |
|
47 | 48 | Version 1.5.1 49 | | 50 |||||||||
| 54 | PREV PACKAGE 55 | NEXT PACKAGE | 56 |57 | FRAMES 58 | NO FRAMES 59 | 66 | 69 | 70 | 71 | | 72 |||||||||
| 85 | Class Summary | 86 ||
|---|---|
| DateTime | 89 |Building block class for an immutable date-time, with no time zone. | 90 |
95 | 96 |
| 99 | Enum Summary | 100 ||
|---|---|
| DateTime.DayOverflow | 103 |Policy for treating 'day-of-the-month overflow' conditions encountered during some date calculations. | 104 |
| DateTime.Unit | 107 |The seven parts of a DateTime object. | 108 |
113 |
124 |
125 |
|
137 | 138 | Version 1.5.1 139 | | 140 |||||||||
| 144 | PREV PACKAGE 145 | NEXT PACKAGE | 146 |147 | FRAMES 148 | NO FRAMES 149 | 156 | 159 | 160 | 161 | | 162 |||||||||
33 |
34 |
|
46 | 47 | Version 1.5.1 48 | | 49 |||||||||
| 53 | PREV 54 | NEXT | 55 |56 | FRAMES 57 | NO FRAMES 58 | 65 | 68 | 69 | 70 | | 71 |||||||||
111 |
112 |
|
124 | 125 | Version 1.5.1 126 | | 127 |||||||||
| 131 | PREV 132 | NEXT | 133 |134 | FRAMES 135 | NO FRAMES 136 | 143 | 146 | 147 | 148 | | 149 |||||||||
33 |
34 |
|
46 | 47 | Version 1.5.1 48 | | 49 |||||||||
| 53 | PREV 54 | NEXT | 55 |56 | FRAMES 57 | NO FRAMES 58 | 65 | 68 | 69 | 70 | | 71 |||||||||
109 |
110 |
|
122 | 123 | Version 1.5.1 124 | | 125 |||||||||
| 129 | PREV 130 | NEXT | 131 |132 | FRAMES 133 | NO FRAMES 134 | 141 | 144 | 145 | 146 | | 147 |||||||||
Example output when you run this class: 13 |
14 | Current date-time in default time zone : 2011-10-24 08:05:59 15 | Current date-time in Cairo : 2011-10-24 13:06:00 (Monday) 16 | Age of someone born May 16, 1995 is : 16 17 | The 3rd Friday of this month is : 2011-10-21 18 | Number of days till Christmas : 62 19 | 90 days from today is : 2012-01-22 20 | 3 months and 5 days from today is : 2012-01-29 21 | Numbers of hours difference between Paris and Perth : 6 22 | The number of weeks since Sep 6, 2010 : 59 23 | This many seconds till midnight : 57240 24 | Output using an ISO format: 2011-10-24T08:06:00 25 | The first day of this week is : 2011-10-23 26 | The number of years the JDK date-time API has been suctorial : 15 27 |28 | */ 29 | public static void main(String... aArgs){ 30 | Examples examples = new Examples(); 31 | examples.currentDateTime(); 32 | examples.currentDateTimeInCairo(); 33 | examples.ageIfBornOnCertainDate(); 34 | examples.optionsExpiry(); 35 | examples.daysTillChristmas(); 36 | examples.whenIs90DaysFromToday(); 37 | examples.whenIs3Months5DaysFromToday(); 38 | examples.hoursDifferenceBetweenParisAndPerth(); 39 | examples.weeksSinceStart(); 40 | examples.timeTillMidnight(); 41 | examples.imitateISOFormat(); 42 | examples.firstDayOfThisWeek(); 43 | examples.jdkDatesSuctorial(); 44 | } 45 | 46 | // PRIVATE 47 | 48 | private static void log(Object aMsg){ 49 | System.out.println(String.valueOf(aMsg)); 50 | } 51 | 52 | /** What is the current date-time in the JRE's default time zone? */ 53 | private void currentDateTime(){ 54 | DateTime now = DateTime.now(TimeZone.getDefault()); 55 | String result = now.format("YYYY-MM-DD hh:mm:ss"); 56 | log("Current date-time in default time zone : " + result); 57 | } 58 | 59 | /** What is the current date-time in Cairo (include weekday)? */ 60 | private void currentDateTimeInCairo(){ 61 | DateTime now = DateTime.now(TimeZone.getTimeZone("Africa/Cairo")); 62 | String result = now.format("YYYY-MM-DD hh:mm:ss (WWWW)", Locale.getDefault()); 63 | log("Current date-time in Cairo : " + result); 64 | } 65 | 66 | /** What's the age of someone born May 16, 1995? */ 67 | private void ageIfBornOnCertainDate(){ 68 | DateTime today = DateTime.today(TimeZone.getDefault()); 69 | DateTime birthdate = DateTime.forDateOnly(1995, 5, 16); 70 | int age = today.getYear() - birthdate.getYear(); 71 | if(today.getDayOfYear() < birthdate.getDayOfYear()){ 72 | age = age - 1; 73 | } 74 | log("Age of someone born May 16, 1995 is : " + age); 75 | } 76 | 77 | /** Stock options expire on the 3rd Friday of this month. What day of the month is that? */ 78 | private void optionsExpiry(){ 79 | DateTime today = DateTime.today(TimeZone.getDefault()); 80 | DateTime firstOfMonth = today.getStartOfMonth(); 81 | int result = 0; 82 | if (firstOfMonth.getWeekDay() == 7){ 83 | result = 21; 84 | } 85 | else { 86 | result = 21 - firstOfMonth.getWeekDay(); 87 | } 88 | DateTime thirdFriday = DateTime.forDateOnly(firstOfMonth.getYear(), firstOfMonth.getMonth(), result); 89 | log("The 3rd Friday of this month is : " + thirdFriday.format("YYYY-MM-DD")); 90 | } 91 | 92 | /** How many days till the next December 25? */ 93 | private void daysTillChristmas(){ 94 | DateTime today = DateTime.today(TimeZone.getDefault()); 95 | DateTime christmas = DateTime.forDateOnly(today.getYear(), 12, 25); 96 | int result = 0; 97 | if(today.isSameDayAs(christmas)){ 98 | // do nothing 99 | } 100 | else if (today.lt(christmas)){ 101 | result = today.numDaysFrom(christmas); 102 | } 103 | else if (today.gt(christmas)){ 104 | DateTime christmasNextYear = DateTime.forDateOnly(today.getYear() + 1, 12, 25); 105 | result = today.numDaysFrom(christmasNextYear); 106 | } 107 | log("Number of days till Christmas : " + result); 108 | } 109 | 110 | /** What day is 90 days from today? */ 111 | private void whenIs90DaysFromToday(){ 112 | DateTime today = DateTime.today(TimeZone.getDefault()); 113 | log("90 days from today is : " + today.plusDays(90).format("YYYY-MM-DD")); 114 | } 115 | 116 | /** What day is 3 months and 5 days from today? */ 117 | private void whenIs3Months5DaysFromToday(){ 118 | DateTime today = DateTime.today(TimeZone.getDefault()); 119 | DateTime result = today.plus(0,3,5,0,0,0,0,DateTime.DayOverflow.FirstDay); 120 | log("3 months and 5 days from today is : " + result.format("YYYY-MM-DD")); 121 | } 122 | 123 | /** Current number of hours difference between Paris, France and Perth, Australia. */ 124 | private void hoursDifferenceBetweenParisAndPerth(){ 125 | //this assumes the time diff is a whole number of hours; other styles are possible 126 | DateTime paris = DateTime.now(TimeZone.getTimeZone("Europe/Paris")); 127 | DateTime perth = DateTime.now(TimeZone.getTimeZone("Australia/Perth")); 128 | int result = perth.getHour() - paris.getHour(); 129 | if( result < 0 ) { 130 | result = result + 24; 131 | } 132 | log("Numbers of hours difference between Paris and Perth : " + result); 133 | } 134 | 135 | /** How many weeks is it since Sep 6, 2010? */ 136 | private void weeksSinceStart(){ 137 | DateTime today = DateTime.today(TimeZone.getDefault()); 138 | DateTime startOfProject = DateTime.forDateOnly(2010, 9, 6); 139 | int result = today.getWeekIndex() - startOfProject.getWeekIndex(); 140 | log("The number of weeks since Sep 6, 2010 : " + result); 141 | } 142 | 143 | /** How much time till midnight? */ 144 | private void timeTillMidnight(){ 145 | DateTime now = DateTime.now(TimeZone.getDefault()); 146 | DateTime midnight = now.plusDays(1).getStartOfDay(); 147 | long result = now.numSecondsFrom(midnight); 148 | log("This many seconds till midnight : " + result); 149 | } 150 | 151 | /** Format using ISO style. */ 152 | private void imitateISOFormat(){ 153 | DateTime now = DateTime.now(TimeZone.getDefault()); 154 | log("Output using an ISO format: " + now.format("YYYY-MM-DDThh:mm:ss")); 155 | } 156 | 157 | private void firstDayOfThisWeek(){ 158 | DateTime today = DateTime.today(TimeZone.getDefault()); 159 | DateTime firstDayThisWeek = today; //start value 160 | int todaysWeekday = today.getWeekDay(); 161 | int SUNDAY = 1; 162 | if(todaysWeekday > SUNDAY){ 163 | int numDaysFromSunday = todaysWeekday - SUNDAY; 164 | firstDayThisWeek = today.minusDays(numDaysFromSunday); 165 | } 166 | log("The first day of this week is : " + firstDayThisWeek); 167 | } 168 | 169 | /** For how many years has the JDK date-time API been suctorial? */ 170 | private void jdkDatesSuctorial(){ 171 | DateTime today = DateTime.today(TimeZone.getDefault()); 172 | DateTime jdkFirstPublished = DateTime.forDateOnly(1996, 1, 23); 173 | int result = today.getYear() - jdkFirstPublished.getYear(); 174 | log("The number of years the JDK date-time API has been suctorial : " + result); 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /classes/hirondelle/date4j/DateTimeParser.java: -------------------------------------------------------------------------------- 1 | package hirondelle.date4j; 2 | 3 | import java.util.regex.Matcher; 4 | import java.util.regex.Pattern; 5 | 6 | /** 7 | Convert a date-time from a string into a {@link DateTime}. 8 | The primary use case for this class is converting date-times from a database ResultSet 9 | into a {@link DateTime}. It can also convert an ISO time, having a 'T' separating the date 10 | from the time. 11 | */ 12 | final class DateTimeParser { 13 | 14 | /** 15 | Thrown when the given string cannot be converted into a DateTime, since it doesn't 16 | have a format allowed by this class. 17 | An unchecked exception. 18 | */ 19 | static final class UnknownDateTimeFormat extends RuntimeException { 20 | private static final long serialVersionUID = -7179421566055773208L; 21 | UnknownDateTimeFormat(String aMessage){ super(aMessage); } 22 | UnknownDateTimeFormat(String aMessage, Throwable aEx){ super(aMessage, aEx); } 23 | } 24 | 25 | DateTime parse(String aDateTime) { 26 | if(aDateTime == null){ 27 | throw new NullPointerException("DateTime string is null"); 28 | } 29 | String dateTime = aDateTime.trim(); 30 | Parts parts = splitIntoDateAndTime(dateTime); 31 | if (parts.hasTwoParts()) { 32 | parseDate(parts.datePart); 33 | parseTime(parts.timePart); 34 | } 35 | else if (parts.hasDateOnly()){ 36 | parseDate(parts.datePart); 37 | } 38 | else if (parts.hasTimeOnly()){ 39 | parseTime(parts.timePart); 40 | } 41 | DateTime result = new DateTime(fYear, fMonth, fDay, fHour, fMinute, fSecond, fNanosecond); 42 | return result; 43 | } 44 | 45 | // PRIVATE 46 | 47 | /** 48 | Gross pattern for dates. 49 | Detailed validation is done by DateTime. 50 | The Group index VARIES for y-m-d according to which option is selected 51 | Year: Group 1, 4, 6 52 | Month: Group 2, 5 53 | Day: Group 3 54 | */ 55 | private static final Pattern DATE = Pattern.compile("(\\d{1,4})-(\\d\\d)-(\\d\\d)|(\\d{1,4})-(\\d\\d)|(\\d{1,4})"); 56 | 57 | /** 58 | Gross pattern for times. 59 | Detailed validation is done by DateTime. 60 | The Group index VARIES for h-m-s-f according to which option is selected 61 | Hour: Group 1, 5, 8, 10 62 | Minute: Group 2, 6, 9 63 | Second: Group 3, 7 64 | Microsecond: Group 4 65 | */ 66 | private static final String CL = "\\:"; //colon is a special character 67 | private static final String TT = "(\\d\\d)"; //colon is a special character 68 | private static final String NUM_DIGITS_FOR_FRACTIONAL_SECONDS = "9"; 69 | private static final Integer NUM_DIGITS = Integer.valueOf(NUM_DIGITS_FOR_FRACTIONAL_SECONDS); 70 | private static final Pattern TIME = Pattern.compile("" + 71 | TT+CL+TT+CL+TT+ "\\." + "(\\d{1," + NUM_DIGITS_FOR_FRACTIONAL_SECONDS + "})" + "|" + 72 | TT+CL+TT+CL+TT+ "|" + 73 | TT+CL+TT+ "|" + 74 | TT 75 | ); 76 | 77 | private static final String COLON = ":"; 78 | private static final int THIRD_POSITION = 2; 79 | 80 | private Integer fYear; 81 | private Integer fMonth; 82 | private Integer fDay; 83 | private Integer fHour; 84 | private Integer fMinute; 85 | private Integer fSecond; 86 | private Integer fNanosecond; 87 | 88 | private class Parts { 89 | String datePart; 90 | String timePart; 91 | boolean hasTwoParts(){ 92 | return datePart != null && timePart != null; 93 | } 94 | boolean hasDateOnly(){ 95 | return timePart == null; 96 | } 97 | boolean hasTimeOnly(){ 98 | return datePart == null; 99 | } 100 | } 101 | 102 | /** Date and time can be separated with a single space, or with a 'T' character (case-sensitive). */ 103 | private Parts splitIntoDateAndTime(String aDateTime){ 104 | Parts result = new Parts(); 105 | int dateTimeSeparator = getDateTimeSeparator(aDateTime); 106 | boolean hasDateTimeSeparator = 0 < dateTimeSeparator && dateTimeSeparator < aDateTime.length(); 107 | if (hasDateTimeSeparator){ 108 | result.datePart = aDateTime.substring(0, dateTimeSeparator); 109 | result.timePart = aDateTime.substring(dateTimeSeparator+1); 110 | } 111 | else if(hasColonInThirdPlace(aDateTime)){ 112 | result.timePart = aDateTime; 113 | } 114 | else { 115 | result.datePart = aDateTime; 116 | } 117 | return result; 118 | } 119 | 120 | /** Return the index of a space character, or of a 'T' character. If not found, return -1.*/ 121 | int getDateTimeSeparator(String aDateTime){ 122 | String SPACE = " "; 123 | int NOT_FOUND = -1; 124 | int result = NOT_FOUND; 125 | result = aDateTime.indexOf(SPACE); 126 | if(result == NOT_FOUND){ 127 | result = aDateTime.indexOf("T"); 128 | } 129 | return result; 130 | } 131 | 132 | private boolean hasColonInThirdPlace(String aDateTime){ 133 | boolean result = false; 134 | if(aDateTime.length() >= THIRD_POSITION){ 135 | result = COLON.equals(aDateTime.substring(THIRD_POSITION,THIRD_POSITION+1)); 136 | } 137 | return result; 138 | } 139 | 140 | private void parseDate(String aDate) { 141 | Matcher matcher = DATE.matcher(aDate); 142 | if (matcher.matches()){ 143 | String year = getGroup(matcher, 1, 4, 6); 144 | if(year !=null ){ 145 | fYear = Integer.valueOf(year); 146 | } 147 | String month = getGroup(matcher, 2, 5); 148 | if(month !=null ){ 149 | fMonth = Integer.valueOf(month); 150 | } 151 | String day = getGroup(matcher, 3); 152 | if(day !=null ){ 153 | fDay = Integer.valueOf(day); 154 | } 155 | } 156 | else { 157 | throw new DateTimeParser.UnknownDateTimeFormat("Unexpected format for date:" + aDate); 158 | } 159 | } 160 | 161 | private String getGroup(Matcher aMatcher, int... aGroupIds){ 162 | String result = null; 163 | for(int id: aGroupIds){ 164 | result = aMatcher.group(id); 165 | if(result!=null) break; 166 | } 167 | return result; 168 | } 169 | 170 | private void parseTime(String aTime) { 171 | Matcher matcher = TIME.matcher(aTime); 172 | if (matcher.matches()){ 173 | String hour = getGroup(matcher, 1, 5, 8, 10); 174 | if(hour !=null ){ 175 | fHour = Integer.valueOf(hour); 176 | } 177 | String minute = getGroup(matcher, 2, 6, 9); 178 | if(minute !=null ){ 179 | fMinute = Integer.valueOf(minute); 180 | } 181 | String second = getGroup(matcher, 3, 7); 182 | if(second !=null ){ 183 | fSecond = Integer.valueOf(second); 184 | } 185 | String decimalSeconds = getGroup(matcher, 4); 186 | if(decimalSeconds !=null ){ 187 | fNanosecond = Integer.valueOf(convertToNanoseconds(decimalSeconds)); 188 | } 189 | } 190 | else { 191 | throw new DateTimeParser.UnknownDateTimeFormat("Unexpected format for time:" + aTime); 192 | } 193 | } 194 | 195 | /** 196 | Convert any number of decimals (1..9) into the form it would have taken if nanos had been used, 197 | by adding any 0's to the right side. 198 | */ 199 | private String convertToNanoseconds(String aDecimalSeconds){ 200 | StringBuilder result = new StringBuilder(aDecimalSeconds); 201 | while( result.length( ) < NUM_DIGITS ){ 202 | result.append("0"); 203 | } 204 | return result.toString(); 205 | } 206 | } 207 | -------------------------------------------------------------------------------- /classes/hirondelle/date4j/Examples.java: -------------------------------------------------------------------------------- 1 | package hirondelle.date4j; 2 | 3 | import java.util.Locale; 4 | import java.util.TimeZone; 5 | 6 | /** Examples of how to use date4j. */ 7 | public final class Examples { 8 | 9 | /** 10 | Run the examples, and output to the console. 11 | 12 |
Example output when you run this class: 13 |
14 | Current date-time in default time zone : 2011-10-24 08:05:59 15 | Current date-time in Cairo : 2011-10-24 13:06:00 (Monday) 16 | Age of someone born May 16, 1995 is : 16 17 | The 3rd Friday of this month is : 2011-10-21 18 | Number of days till Christmas : 62 19 | 90 days from today is : 2012-01-22 20 | 3 months and 5 days from today is : 2012-01-29 21 | Numbers of hours difference between Paris and Perth : 6 22 | The number of weeks since Sep 6, 2010 : 59 23 | This many seconds till midnight : 57240 24 | Output using an ISO format: 2011-10-24T08:06:00 25 | The first day of this week is : 2011-10-23 26 | The number of years the JDK date-time API has been suctorial : 15 27 |28 | */ 29 | public static void main(String... aArgs){ 30 | Examples examples = new Examples(); 31 | examples.currentDateTime(); 32 | examples.currentDateTimeInCairo(); 33 | examples.ageIfBornOnCertainDate(); 34 | examples.optionsExpiry(); 35 | examples.daysTillChristmas(); 36 | examples.whenIs90DaysFromToday(); 37 | examples.whenIs3Months5DaysFromToday(); 38 | examples.hoursDifferenceBetweenParisAndPerth(); 39 | examples.weeksSinceStart(); 40 | examples.timeTillMidnight(); 41 | examples.imitateISOFormat(); 42 | examples.firstDayOfThisWeek(); 43 | examples.jdkDatesSuctorial(); 44 | } 45 | 46 | // PRIVATE 47 | 48 | private static void log(Object aMsg){ 49 | System.out.println(String.valueOf(aMsg)); 50 | } 51 | 52 | /** What is the current date-time in the JRE's default time zone? */ 53 | private void currentDateTime(){ 54 | DateTime now = DateTime.now(TimeZone.getDefault()); 55 | String result = now.format("YYYY-MM-DD hh:mm:ss"); 56 | log("Current date-time in default time zone : " + result); 57 | } 58 | 59 | /** What is the current date-time in Cairo (include weekday)? */ 60 | private void currentDateTimeInCairo(){ 61 | DateTime now = DateTime.now(TimeZone.getTimeZone("Africa/Cairo")); 62 | String result = now.format("YYYY-MM-DD hh:mm:ss (WWWW)", Locale.getDefault()); 63 | log("Current date-time in Cairo : " + result); 64 | } 65 | 66 | /** What's the age of someone born May 16, 1995? */ 67 | private void ageIfBornOnCertainDate(){ 68 | DateTime today = DateTime.today(TimeZone.getDefault()); 69 | DateTime birthdate = DateTime.forDateOnly(1995, 5, 16); 70 | int age = today.getYear() - birthdate.getYear(); 71 | if(today.getDayOfYear() < birthdate.getDayOfYear()){ 72 | age = age - 1; 73 | } 74 | log("Age of someone born May 16, 1995 is : " + age); 75 | } 76 | 77 | /** Stock options expire on the 3rd Friday of this month. What day of the month is that? */ 78 | private void optionsExpiry(){ 79 | DateTime today = DateTime.today(TimeZone.getDefault()); 80 | DateTime firstOfMonth = today.getStartOfMonth(); 81 | int result = 0; 82 | if (firstOfMonth.getWeekDay() == 7){ 83 | result = 21; 84 | } 85 | else { 86 | result = 21 - firstOfMonth.getWeekDay(); 87 | } 88 | DateTime thirdFriday = DateTime.forDateOnly(firstOfMonth.getYear(), firstOfMonth.getMonth(), result); 89 | log("The 3rd Friday of this month is : " + thirdFriday.format("YYYY-MM-DD")); 90 | } 91 | 92 | /** How many days till the next December 25? */ 93 | private void daysTillChristmas(){ 94 | DateTime today = DateTime.today(TimeZone.getDefault()); 95 | DateTime christmas = DateTime.forDateOnly(today.getYear(), 12, 25); 96 | int result = 0; 97 | if(today.isSameDayAs(christmas)){ 98 | // do nothing 99 | } 100 | else if (today.lt(christmas)){ 101 | result = today.numDaysFrom(christmas); 102 | } 103 | else if (today.gt(christmas)){ 104 | DateTime christmasNextYear = DateTime.forDateOnly(today.getYear() + 1, 12, 25); 105 | result = today.numDaysFrom(christmasNextYear); 106 | } 107 | log("Number of days till Christmas : " + result); 108 | } 109 | 110 | /** What day is 90 days from today? */ 111 | private void whenIs90DaysFromToday(){ 112 | DateTime today = DateTime.today(TimeZone.getDefault()); 113 | log("90 days from today is : " + today.plusDays(90).format("YYYY-MM-DD")); 114 | } 115 | 116 | /** What day is 3 months and 5 days from today? */ 117 | private void whenIs3Months5DaysFromToday(){ 118 | DateTime today = DateTime.today(TimeZone.getDefault()); 119 | DateTime result = today.plus(0,3,5,0,0,0,0,DateTime.DayOverflow.FirstDay); 120 | log("3 months and 5 days from today is : " + result.format("YYYY-MM-DD")); 121 | } 122 | 123 | /** Current number of hours difference between Paris, France and Perth, Australia. */ 124 | private void hoursDifferenceBetweenParisAndPerth(){ 125 | //this assumes the time diff is a whole number of hours; other styles are possible 126 | DateTime paris = DateTime.now(TimeZone.getTimeZone("Europe/Paris")); 127 | DateTime perth = DateTime.now(TimeZone.getTimeZone("Australia/Perth")); 128 | int result = perth.getHour() - paris.getHour(); 129 | if( result < 0 ) { 130 | result = result + 24; 131 | } 132 | log("Numbers of hours difference between Paris and Perth : " + result); 133 | } 134 | 135 | /** How many weeks is it since Sep 6, 2010? */ 136 | private void weeksSinceStart(){ 137 | DateTime today = DateTime.today(TimeZone.getDefault()); 138 | DateTime startOfProject = DateTime.forDateOnly(2010, 9, 6); 139 | int result = today.getWeekIndex() - startOfProject.getWeekIndex(); 140 | log("The number of weeks since Sep 6, 2010 : " + result); 141 | } 142 | 143 | /** How much time till midnight? */ 144 | private void timeTillMidnight(){ 145 | DateTime now = DateTime.now(TimeZone.getDefault()); 146 | DateTime midnight = now.plusDays(1).getStartOfDay(); 147 | long result = now.numSecondsFrom(midnight); 148 | log("This many seconds till midnight : " + result); 149 | } 150 | 151 | /** Format using ISO style. */ 152 | private void imitateISOFormat(){ 153 | DateTime now = DateTime.now(TimeZone.getDefault()); 154 | log("Output using an ISO format: " + now.format("YYYY-MM-DDThh:mm:ss")); 155 | } 156 | 157 | private void firstDayOfThisWeek(){ 158 | DateTime today = DateTime.today(TimeZone.getDefault()); 159 | DateTime firstDayThisWeek = today; //start value 160 | int todaysWeekday = today.getWeekDay(); 161 | int SUNDAY = 1; 162 | if(todaysWeekday > SUNDAY){ 163 | int numDaysFromSunday = todaysWeekday - SUNDAY; 164 | firstDayThisWeek = today.minusDays(numDaysFromSunday); 165 | } 166 | log("The first day of this week is : " + firstDayThisWeek); 167 | } 168 | 169 | /** For how many years has the JDK date-time API been suctorial? */ 170 | private void jdkDatesSuctorial(){ 171 | DateTime today = DateTime.today(TimeZone.getDefault()); 172 | DateTime jdkFirstPublished = DateTime.forDateOnly(1996, 1, 23); 173 | int result = today.getYear() - jdkFirstPublished.getYear(); 174 | log("The number of years the JDK date-time API has been suctorial : " + result); 175 | } 176 | 177 | } -------------------------------------------------------------------------------- /docs/javadoc/help-doc.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 |
33 |
34 |
|
46 | 47 | Version 1.5.1 48 | | 49 |||||||||
| 53 | PREV 54 | NEXT | 55 |56 | FRAMES 57 | NO FRAMES 58 | 65 | 68 | 69 | 70 | | 71 |||||||||
84 | 85 |87 |86 | The Overview page is the front page of this API document and provides a list of all packages with a summary for each. This page can also contain an overall description of the set of packages.
90 | 91 |95 |92 | Each package has a page that contains a list of its classes and interfaces, with a summary for each. This page can contain four categories:
93 |
94 |- Interfaces (italic)
- Classes
- Enums
- Exceptions
- Errors
- Annotation Types
98 | 99 |107 | 108 |100 | Each class, interface, nested class and nested interface has its own separate page. Each of these pages has three sections consisting of a class/interface description, summary tables, and detailed member descriptions:
101 |
106 | Each summary entry contains the first sentence from the detailed description for that item. The summary entries are alphabetical, while the detailed descriptions are in the order they appear in the source code. This preserves the logical groupings established by the programmer.- Class inheritance diagram
- Direct Subclasses
- All Known Subinterfaces
- All Known Implementing Classes
- Class/interface declaration
- Class/interface description 102 |
103 |
- Nested Class Summary
- Field Summary
- Constructor Summary
- Method Summary 104 |
105 |
- Field Detail
- Constructor Detail
- Method Detail
111 | 112 |116 | 117 |113 | Each annotation type has its own separate page with the following sections:
114 |
115 |- Annotation Type declaration
- Annotation Type description
- Required Element Summary
- Optional Element Summary
- Element Detail
120 | 121 |125 |122 | Each enum has its own separate page with the following sections:
123 |
124 |- Enum declaration
- Enum description
- Enum Constant Summary
- Enum Constant Detail
128 | There is a Class Hierarchy page for all packages, plus a hierarchy for each package. Each hierarchy page contains a list of classes and a list of interfaces. The classes are organized by inheritance structure starting with131 |java.lang.Object. The interfaces do not inherit fromjava.lang.Object.129 |
130 |- When viewing the Overview page, clicking on "Tree" displays the hierarchy for all packages.
- When viewing a particular package, class or interface page, clicking "Tree" displays the hierarchy for only that package.
134 | The Deprecated API page lists all of the API that have been deprecated. A deprecated API is not recommended for use, generally due to improvements, and a replacement API is usually given. Deprecated APIs may be removed in future implementations.135 |
138 | The Index contains an alphabetic list of all classes, interfaces, constructors, methods, and fields.139 |
145 |
149 |
153 |
154 |
155 | This help file applies to API documentation generated using the standard doclet.
156 |
157 |
158 |
167 |
168 |
|
180 | 181 | Version 1.5.1 182 | | 183 |||||||||
| 187 | PREV 188 | NEXT | 189 |190 | FRAMES 191 | NO FRAMES 192 | 199 | 202 | 203 | 204 | | 205 |||||||||
33 |
34 |
|
46 | 47 | Version 1.5.1 48 | | 49 |||||||||
| 53 | PREV 54 | NEXT | 55 |56 | FRAMES 57 | NO FRAMES 58 | 65 | 68 | 69 | 70 | | 71 |||||||||
| 86 | Package hirondelle.date4j | 87 |
|---|
| 95 | Class hirondelle.date4j.DateTime extends Object implements Serializable | 96 |
|---|
100 | serialVersionUID: -1300068157085493891L 101 | 102 |
| 107 | Serialization Methods | 108 |
|---|
115 | private void readObject(ObjectInputStream aInputStream) 116 | throws ClassNotFoundException, 117 | IOException118 |
122 |
ClassNotFoundException
126 | IOException133 | private void writeObject(ObjectOutputStream aOutputStream) 134 | throws IOException135 |
139 |
IOException| 149 | Serialized Fields | 150 |
|---|
156 | String fDateTime157 |
160 |
167 | Integer fYear168 |
176 | Integer fMonth177 |
185 | Integer fDay186 |
194 | Integer fHour195 |
203 | Integer fMinute204 |
212 | Integer fSecond213 |
221 | Integer fNanosecond222 |
230 | boolean fIsAlreadyParsed231 |
234 |
241 | int fHashCode242 |
248 |
257 |
258 |
|
270 | 271 | Version 1.5.1 272 | | 273 |||||||||
| 277 | PREV 278 | NEXT | 279 |280 | FRAMES 281 | NO FRAMES 282 | 289 | 292 | 293 | 294 | | 295 |||||||||
This class is intended only for cases where toString is used in 17 | an informal manner (usually for logging and stack traces). It is especially 18 | suited for public classes which model domain objects. 19 | 20 | Here is an example of a return value of the {@link #getText} method : 21 |
22 | hirondelle.web4j.model.MyUser {
23 | LoginName: Bob
24 | LoginPassword: ****
25 | EmailAddress: bob@blah.com
26 | StarRating: 1
27 | FavoriteTheory: Quantum Chromodynamics
28 | SendCard: true
29 | Age: 42
30 | DesiredSalary: 42000
31 | BirthDate: Sat Feb 26 13:45:43 EST 2005
32 | }
33 |
34 | (Previous versions of this classes used indentation within the braces. That has
35 | been removed, since it displays poorly when nesting occurs.)
36 |
37 | Here are two more examples, using classes taken from the JDK : 38 |
39 | java.util.StringTokenizer {
40 | nextElement: This
41 | hasMoreElements: true
42 | countTokens: 3
43 | nextToken: is
44 | hasMoreTokens: true
45 | }
46 |
47 | java.util.ArrayList {
48 | size: 3
49 | toArray: [blah, blah, blah]
50 | isEmpty: false
51 | }
52 |
53 |
54 | There are two use cases for this class. The typical use case is :
55 |
56 | public String toString() {
57 | return ToStringUtil.getText(this);
58 | }
59 |
60 |
61 | However, there is a case where this typical style can
62 | fail catastrophically : when two objects reference each other, and each
63 | has toString implemented as above, then the program will loop
64 | indefinitely!
65 |
66 | As a remedy for this problem, the following variation is provided : 67 |
68 | public String toString() {
69 | return ToStringUtil.getTextAvoidCyclicRefs(this, Product.class, "getId");
70 | }
71 |
72 | Here, the usual behavior is overridden for any method
73 | which returns a Product : instead of calling Product.toString,
74 | the return value of Product.getId() is used to textually represent
75 | the object.
76 | */
77 | final class ToStringUtil {
78 |
79 | /**
80 | Return an informal textual description of an object.
81 | It is highly recommened that the caller not rely on details 82 | of the returned String. See class description for examples of return 83 | values. 84 | 85 |
WARNING: If two classes have cyclic references 86 | (that is, each has a reference to the other), then infinite looping will result 87 | if both call this method! To avoid this problem, use getText 88 | for one of the classes, and {@link #getTextAvoidCyclicRefs} for the other class. 89 | 90 |
The only items which contribute to the result are the class name, and all 91 | no-argument public methods which return a value. As well, methods 92 | defined by the Object class, and factory methods which return an 93 | Object of the native class ("getInstance" methods) do not contribute. 94 | 95 |
Items are converted to a String simply by calling their 96 | toString method, with these exceptions : 97 |
If the method name follows the pattern getXXX, then the word 'get' 104 | is removed from the presented result. 105 | 106 | @param aObject the object for which a toString result is required. 107 | */ 108 | static String getText(Object aObject) { 109 | return getTextAvoidCyclicRefs(aObject, null, null); 110 | } 111 | 112 | /** 113 | As in {@link #getText}, but, for return values which are instances of 114 | aSpecialClass, then call aMethodName instead of toString. 115 | 116 |
If aSpecialClass and aMethodName are null, then the
117 | behavior is exactly the same as calling {@link #getText}.
118 | */
119 | static String getTextAvoidCyclicRefs(Object aObject, Class aSpecialClass, String aMethodName) {
120 | StringBuilder result = new StringBuilder();
121 | addStartLine(aObject, result);
122 |
123 | Method[] methods = aObject.getClass().getDeclaredMethods();
124 | for(Method method: methods){
125 | if ( isContributingMethod(method, aObject.getClass()) ){
126 | addLineForGetXXXMethod(aObject, method, result, aSpecialClass, aMethodName);
127 | }
128 | }
129 |
130 | addEndLine(result);
131 | return result.toString();
132 | }
133 |
134 | // PRIVATE //
135 |
136 | /*
137 | Names of methods in the Object class which are ignored.
138 | */
139 | private static final String fGET_CLASS = "getClass";
140 | private static final String fCLONE = "clone";
141 | private static final String fHASH_CODE = "hashCode";
142 | private static final String fTO_STRING = "toString";
143 |
144 | private static final String fGET = "get";
145 | private static final Object[] fNO_ARGS = new Object[0];
146 | private static final Class[] fNO_PARAMS = new Class[0];
147 | /*
148 | Previous versions of this class indented the data within a block.
149 | That style breaks when one object references another. The indentation
150 | has been removed, but this variable has been retained, since others might
151 | prefer the indentation anyway.
152 | */
153 | private static final String fINDENT = "";
154 | private static final String fAVOID_CIRCULAR_REFERENCES = "[circular reference]";
155 | private static final Logger fLogger = Util.getLogger(ToStringUtil.class);
156 | private static final String NEW_LINE = System.getProperty("line.separator");
157 |
158 | private static Pattern PASSWORD_PATTERN = Pattern.compile("password", Pattern.CASE_INSENSITIVE);
159 | private static String HIDDEN_PASSWORD_VALUE = "****";
160 |
161 | //prevent construction by the caller
162 | private ToStringUtil() {
163 | //empty
164 | }
165 |
166 | private static void addStartLine(Object aObject, StringBuilder aResult){
167 | aResult.append( aObject.getClass().getName() );
168 | aResult.append(" {");
169 | aResult.append(NEW_LINE);
170 | }
171 |
172 | private static void addEndLine(StringBuilder aResult){
173 | aResult.append("}");
174 | aResult.append(NEW_LINE);
175 | }
176 |
177 | /**
178 | Return true only if aMethod is public, takes no args,
179 | returns a value whose class is not the native class, is not a method of
180 | Object.
181 | */
182 | private static boolean isContributingMethod(Method aMethod, Class aNativeClass){
183 | boolean isPublic = Modifier.isPublic( aMethod.getModifiers() );
184 | boolean hasNoArguments = aMethod.getParameterTypes().length == 0;
185 | boolean hasReturnValue = aMethod.getReturnType() != Void.TYPE;
186 | boolean returnsNativeObject = aMethod.getReturnType() == aNativeClass;
187 | boolean isMethodOfObjectClass =
188 | aMethod.getName().equals(fCLONE) ||
189 | aMethod.getName().equals(fGET_CLASS) ||
190 | aMethod.getName().equals(fHASH_CODE) ||
191 | aMethod.getName().equals(fTO_STRING)
192 | ;
193 | return
194 | isPublic &&
195 | hasNoArguments &&
196 | hasReturnValue &&
197 | ! isMethodOfObjectClass &&
198 | ! returnsNativeObject;
199 | }
200 |
201 | private static void addLineForGetXXXMethod(
202 | Object aObject,
203 | Method aMethod,
204 | StringBuilder aResult,
205 | Class aCircularRefClass,
206 | String aCircularRefMethodName
207 | ){
208 | aResult.append(fINDENT);
209 | aResult.append( getMethodNameMinusGet(aMethod) );
210 | aResult.append(": ");
211 | Object returnValue = getMethodReturnValue(aObject, aMethod);
212 | if ( returnValue != null && returnValue.getClass().isArray() ) {
213 | aResult.append( Util.getArrayAsString(returnValue) );
214 | }
215 | else {
216 | if (aCircularRefClass == null) {
217 | aResult.append( returnValue );
218 | }
219 | else {
220 | if (aCircularRefClass == returnValue.getClass()) {
221 | Method method = getMethodFromName(aCircularRefClass, aCircularRefMethodName);
222 | if ( isContributingMethod(method, aCircularRefClass)){
223 | returnValue = getMethodReturnValue(returnValue, method);
224 | aResult.append( returnValue );
225 | }
226 | else {
227 | aResult.append(fAVOID_CIRCULAR_REFERENCES);
228 | }
229 | }
230 | }
231 | }
232 | aResult.append( NEW_LINE );
233 | }
234 |
235 | private static String getMethodNameMinusGet(Method aMethod){
236 | String result = aMethod.getName();
237 | if (result.startsWith(fGET) ) {
238 | result = result.substring(fGET.length());
239 | }
240 | return result;
241 | }
242 |
243 | /** Return value is possibly-null. */
244 | private static Object getMethodReturnValue(Object aObject, Method aMethod){
245 | Object result = null;
246 | try {
247 | result = aMethod.invoke(aObject, fNO_ARGS);
248 | }
249 | catch (IllegalAccessException ex){
250 | vomit(aObject, aMethod);
251 | }
252 | catch (InvocationTargetException ex){
253 | vomit(aObject, aMethod);
254 | }
255 | result = dontShowPasswords(result, aMethod);
256 | return result;
257 | }
258 |
259 | private static Method getMethodFromName(Class aSpecialClass, String aMethodName){
260 | Method result = null;
261 | try {
262 | result = aSpecialClass.getMethod(aMethodName, fNO_PARAMS);
263 | }
264 | catch ( NoSuchMethodException ex){
265 | vomit(aSpecialClass, aMethodName);
266 | }
267 | return result;
268 | }
269 |
270 |
271 | private static void vomit(Object aObject, Method aMethod){
272 | fLogger.severe(
273 | "Cannot get return value using reflection. Class: " +
274 | aObject.getClass().getName() +
275 | " Method: " +
276 | aMethod.getName()
277 | );
278 | }
279 |
280 | private static void vomit(Class aSpecialClass, String aMethodName){
281 | fLogger.severe(
282 | "Reflection fails to get no-arg method named: " +
283 | Util.quote(aMethodName) +
284 | " for class: " +
285 | aSpecialClass.getName()
286 | );
287 | }
288 |
289 | private static Object dontShowPasswords(Object aReturnValue, Method aMethod){
290 | Object result = aReturnValue;
291 | Matcher matcher = PASSWORD_PATTERN.matcher(aMethod.getName());
292 | if ( matcher.find()) {
293 | result = HIDDEN_PASSWORD_VALUE;
294 | }
295 | return result;
296 | }
297 |
298 | /*
299 | Two informal classes with cyclic references, used for testing.
300 | */
301 | private static final class Ping {
302 | public void setPong(Pong aPong){fPong = aPong; }
303 | public Pong getPong(){ return fPong; }
304 | public Integer getId() { return new Integer(123); }
305 | public String getUserPassword(){ return "blah"; }
306 | public String toString() {
307 | return getText(this);
308 | }
309 | private Pong fPong;
310 | }
311 | private static final class Pong {
312 | public void setPing(Ping aPing){ fPing = aPing; }
313 | public Ping getPing() { return fPing; }
314 | public String toString() {
315 | return getTextAvoidCyclicRefs(this, Ping.class, "getId");
316 | //to see the infinite looping, use this instead :
317 | //return getText(this);
318 | }
319 | private Ping fPing;
320 | }
321 |
322 | /**
323 | Informal test harness.
324 | */
325 | public static void main (String... args) {
326 | List
107 | The seven parts of a DateTime object. The DAY represents the day of the month (1..31), not the weekday.
108 |
109 |
110 |
111 |
315 |
333 |
10 | package hirondelle.date4j;
11 |
12 | import java.util.Locale;
13 | import java.util.TimeZone;
14 |
15 | /** Examples of how to use date4j. */
16 | public final class Examples {
17 |
18 | /**
19 | Run the examples, and output to the console.
20 |
21 | <P>Example output when you run this class:
22 | <PRE>
23 | Current date-time in default time zone : 2011-10-24 08:05:59
24 | Current date-time in Cairo : 2011-10-24 13:06:00 (Monday)
25 | Age of someone born May 16, 1995 is : 16
26 | The 3rd Friday of this month is : 2011-10-21
27 | Number of days till Christmas : 62
28 | 90 days from today is : 2012-01-22
29 | 3 months and 5 days from today is : 2012-01-29
30 | Numbers of hours difference between Paris and Perth : 6
31 | The number of weeks since Sep 6, 2010 : 59
32 | This many seconds till midnight : 57240
33 | Output using an ISO format: 2011-10-24T08:06:00
34 | The first day of this week is : 2011-10-23
35 | The number of years the JDK date-time API has been suctorial : 15
36 | </PRE>
37 | */
38 | public static void main(String... aArgs){
39 | Examples examples = new Examples();
40 | examples.currentDateTime();
41 | examples.currentDateTimeInCairo();
42 | examples.ageIfBornOnCertainDate();
43 | examples.optionsExpiry();
44 | examples.daysTillChristmas();
45 | examples.whenIs90DaysFromToday();
46 | examples.whenIs3Months5DaysFromToday();
47 | examples.hoursDifferenceBetweenParisAndPerth();
48 | examples.weeksSinceStart();
49 | examples.timeTillMidnight();
50 | examples.imitateISOFormat();
51 | examples.firstDayOfThisWeek();
52 | examples.jdkDatesSuctorial();
53 | }
54 |
55 | // PRIVATE
56 |
57 | private static void log(Object aMsg){
58 | System.out.println(String.valueOf(aMsg));
59 | }
60 |
61 | /** What is the current date-time in the JRE's default time zone? */
62 | private void currentDateTime(){
63 | DateTime now = DateTime.now(TimeZone.getDefault());
64 | String result = now.format("YYYY-MM-DD hh:mm:ss");
65 | log("Current date-time in default time zone : " + result);
66 | }
67 |
68 | /** What is the current date-time in Cairo (include weekday)? */
69 | private void currentDateTimeInCairo(){
70 | DateTime now = DateTime.now(TimeZone.getTimeZone("Africa/Cairo"));
71 | String result = now.format("YYYY-MM-DD hh:mm:ss (WWWW)", Locale.getDefault());
72 | log("Current date-time in Cairo : " + result);
73 | }
74 |
75 | /** What's the age of someone born May 16, 1995? */
76 | private void ageIfBornOnCertainDate(){
77 | DateTime today = DateTime.today(TimeZone.getDefault());
78 | DateTime birthdate = DateTime.forDateOnly(1995, 5, 16);
79 | int age = today.getYear() - birthdate.getYear();
80 | if(today.getDayOfYear() < birthdate.getDayOfYear()){
81 | age = age - 1;
82 | }
83 | log("Age of someone born May 16, 1995 is : " + age);
84 | }
85 |
86 | /** Stock options expire on the 3rd Friday of this month. What day of the month is that? */
87 | private void optionsExpiry(){
88 | DateTime today = DateTime.today(TimeZone.getDefault());
89 | DateTime firstOfMonth = today.getStartOfMonth();
90 | int result = 0;
91 | if (firstOfMonth.getWeekDay() == 7){
92 | result = 21;
93 | }
94 | else {
95 | result = 21 - firstOfMonth.getWeekDay();
96 | }
97 | DateTime thirdFriday = DateTime.forDateOnly(firstOfMonth.getYear(), firstOfMonth.getMonth(), result);
98 | log("The 3rd Friday of this month is : " + thirdFriday.format("YYYY-MM-DD"));
99 | }
100 |
101 | /** How many days till the next December 25? */
102 | private void daysTillChristmas(){
103 | DateTime today = DateTime.today(TimeZone.getDefault());
104 | DateTime christmas = DateTime.forDateOnly(today.getYear(), 12, 25);
105 | int result = 0;
106 | if(today.isSameDayAs(christmas)){
107 | // do nothing
108 | }
109 | else if (today.lt(christmas)){
110 | result = today.numDaysFrom(christmas);
111 | }
112 | else if (today.gt(christmas)){
113 | DateTime christmasNextYear = DateTime.forDateOnly(today.getYear() + 1, 12, 25);
114 | result = today.numDaysFrom(christmasNextYear);
115 | }
116 | log("Number of days till Christmas : " + result);
117 | }
118 |
119 | /** What day is 90 days from today? */
120 | private void whenIs90DaysFromToday(){
121 | DateTime today = DateTime.today(TimeZone.getDefault());
122 | log("90 days from today is : " + today.plusDays(90).format("YYYY-MM-DD"));
123 | }
124 |
125 | /** What day is 3 months and 5 days from today? */
126 | private void whenIs3Months5DaysFromToday(){
127 | DateTime today = DateTime.today(TimeZone.getDefault());
128 | DateTime result = today.plus(0,3,5,0,0,0,0,DateTime.DayOverflow.FirstDay);
129 | log("3 months and 5 days from today is : " + result.format("YYYY-MM-DD"));
130 | }
131 |
132 | /** Current number of hours difference between Paris, France and Perth, Australia. */
133 | private void hoursDifferenceBetweenParisAndPerth(){
134 | //this assumes the time diff is a whole number of hours; other styles are possible
135 | DateTime paris = DateTime.now(TimeZone.getTimeZone("Europe/Paris"));
136 | DateTime perth = DateTime.now(TimeZone.getTimeZone("Australia/Perth"));
137 | int result = perth.getHour() - paris.getHour();
138 | if( result < 0 ) {
139 | result = result + 24;
140 | }
141 | log("Numbers of hours difference between Paris and Perth : " + result);
142 | }
143 |
144 | /** How many weeks is it since Sep 6, 2010? */
145 | private void weeksSinceStart(){
146 | DateTime today = DateTime.today(TimeZone.getDefault());
147 | DateTime startOfProject = DateTime.forDateOnly(2010, 9, 6);
148 | int result = today.getWeekIndex() - startOfProject.getWeekIndex();
149 | log("The number of weeks since Sep 6, 2010 : " + result);
150 | }
151 |
152 | /** How much time till midnight? */
153 | private void timeTillMidnight(){
154 | DateTime now = DateTime.now(TimeZone.getDefault());
155 | DateTime midnight = now.plusDays(1).getStartOfDay();
156 | long result = now.numSecondsFrom(midnight);
157 | log("This many seconds till midnight : " + result);
158 | }
159 |
160 | /** Format using ISO style. */
161 | private void imitateISOFormat(){
162 | DateTime now = DateTime.now(TimeZone.getDefault());
163 | log("Output using an ISO format: " + now.format("YYYY-MM-DDThh:mm:ss"));
164 | }
165 |
166 | private void firstDayOfThisWeek(){
167 | DateTime today = DateTime.today(TimeZone.getDefault());
168 | DateTime firstDayThisWeek = today; //start value
169 | int todaysWeekday = today.getWeekDay();
170 | int SUNDAY = 1;
171 | if(todaysWeekday > SUNDAY){
172 | int numDaysFromSunday = todaysWeekday - SUNDAY;
173 | firstDayThisWeek = today.minusDays(numDaysFromSunday);
174 | }
175 | log("The first day of this week is : " + firstDayThisWeek);
176 | }
177 |
178 | /** For how many years has the JDK date-time API been suctorial? */
179 | private void jdkDatesSuctorial(){
180 | DateTime today = DateTime.today(TimeZone.getDefault());
181 | DateTime jdkFirstPublished = DateTime.forDateOnly(1996, 1, 23);
182 | int result = today.getYear() - jdkFirstPublished.getYear();
183 | log("The number of years the JDK date-time API has been suctorial : " + result);
184 | }
185 |
186 | }
187 |
188 |
189 |
190 |
--------------------------------------------------------------------------------
/docs/javadoc/src-html/hirondelle/date4j/DateTimeParser.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
10 | package hirondelle.date4j;
11 |
12 | import java.util.regex.Matcher;
13 | import java.util.regex.Pattern;
14 |
15 | /**
16 | Convert a date-time from a string into a {@link DateTime}.
17 | The primary use case for this class is converting date-times from a database <tt>ResultSet</tt>
18 | into a {@link DateTime}. It can also convert an ISO time, having a 'T' separating the date
19 | from the time.
20 | */
21 | final class DateTimeParser {
22 |
23 | /**
24 | Thrown when the given string cannot be converted into a <tt>DateTime</tt>, since it doesn't
25 | have a format allowed by this class.
26 | An unchecked exception.
27 | */
28 | static final class UnknownDateTimeFormat extends RuntimeException {
29 | private static final long serialVersionUID = -7179421566055773208L;
30 | UnknownDateTimeFormat(String aMessage){ super(aMessage); }
31 | UnknownDateTimeFormat(String aMessage, Throwable aEx){ super(aMessage, aEx); }
32 | }
33 |
34 | DateTime parse(String aDateTime) {
35 | if(aDateTime == null){
36 | throw new NullPointerException("DateTime string is null");
37 | }
38 | String dateTime = aDateTime.trim();
39 | Parts parts = splitIntoDateAndTime(dateTime);
40 | if (parts.hasTwoParts()) {
41 | parseDate(parts.datePart);
42 | parseTime(parts.timePart);
43 | }
44 | else if (parts.hasDateOnly()){
45 | parseDate(parts.datePart);
46 | }
47 | else if (parts.hasTimeOnly()){
48 | parseTime(parts.timePart);
49 | }
50 | DateTime result = new DateTime(fYear, fMonth, fDay, fHour, fMinute, fSecond, fNanosecond);
51 | return result;
52 | }
53 |
54 | // PRIVATE
55 |
56 | /**
57 | Gross pattern for dates.
58 | Detailed validation is done by DateTime.
59 | The Group index VARIES for y-m-d according to which option is selected
60 | Year: Group 1, 4, 6
61 | Month: Group 2, 5
62 | Day: Group 3
63 | */
64 | private static final Pattern DATE = Pattern.compile("(\\d{1,4})-(\\d\\d)-(\\d\\d)|(\\d{1,4})-(\\d\\d)|(\\d{1,4})");
65 |
66 | /**
67 | Gross pattern for times.
68 | Detailed validation is done by DateTime.
69 | The Group index VARIES for h-m-s-f according to which option is selected
70 | Hour: Group 1, 5, 8, 10
71 | Minute: Group 2, 6, 9
72 | Second: Group 3, 7
73 | Microsecond: Group 4
74 | */
75 | private static final String CL = "\\:"; //colon is a special character
76 | private static final String TT = "(\\d\\d)"; //colon is a special character
77 | private static final String NUM_DIGITS_FOR_FRACTIONAL_SECONDS = "9";
78 | private static final Integer NUM_DIGITS = Integer.valueOf(NUM_DIGITS_FOR_FRACTIONAL_SECONDS);
79 | private static final Pattern TIME = Pattern.compile("" +
80 | TT+CL+TT+CL+TT+ "\\." + "(\\d{1," + NUM_DIGITS_FOR_FRACTIONAL_SECONDS + "})" + "|" +
81 | TT+CL+TT+CL+TT+ "|" +
82 | TT+CL+TT+ "|" +
83 | TT
84 | );
85 |
86 | private static final String COLON = ":";
87 | private static final int THIRD_POSITION = 2;
88 |
89 | private Integer fYear;
90 | private Integer fMonth;
91 | private Integer fDay;
92 | private Integer fHour;
93 | private Integer fMinute;
94 | private Integer fSecond;
95 | private Integer fNanosecond;
96 |
97 | private class Parts {
98 | String datePart;
99 | String timePart;
100 | boolean hasTwoParts(){
101 | return datePart != null && timePart != null;
102 | }
103 | boolean hasDateOnly(){
104 | return timePart == null;
105 | }
106 | boolean hasTimeOnly(){
107 | return datePart == null;
108 | }
109 | }
110 |
111 | /** Date and time can be separated with a single space, or with a 'T' character (case-sensitive). */
112 | private Parts splitIntoDateAndTime(String aDateTime){
113 | Parts result = new Parts();
114 | int dateTimeSeparator = getDateTimeSeparator(aDateTime);
115 | boolean hasDateTimeSeparator = 0 < dateTimeSeparator && dateTimeSeparator < aDateTime.length();
116 | if (hasDateTimeSeparator){
117 | result.datePart = aDateTime.substring(0, dateTimeSeparator);
118 | result.timePart = aDateTime.substring(dateTimeSeparator+1);
119 | }
120 | else if(hasColonInThirdPlace(aDateTime)){
121 | result.timePart = aDateTime;
122 | }
123 | else {
124 | result.datePart = aDateTime;
125 | }
126 | return result;
127 | }
128 |
129 | /** Return the index of a space character, or of a 'T' character. If not found, return -1.*/
130 | int getDateTimeSeparator(String aDateTime){
131 | String SPACE = " ";
132 | int NOT_FOUND = -1;
133 | int result = NOT_FOUND;
134 | result = aDateTime.indexOf(SPACE);
135 | if(result == NOT_FOUND){
136 | result = aDateTime.indexOf("T");
137 | }
138 | return result;
139 | }
140 |
141 | private boolean hasColonInThirdPlace(String aDateTime){
142 | boolean result = false;
143 | if(aDateTime.length() >= THIRD_POSITION){
144 | result = COLON.equals(aDateTime.substring(THIRD_POSITION,THIRD_POSITION+1));
145 | }
146 | return result;
147 | }
148 |
149 | private void parseDate(String aDate) {
150 | Matcher matcher = DATE.matcher(aDate);
151 | if (matcher.matches()){
152 | String year = getGroup(matcher, 1, 4, 6);
153 | if(year !=null ){
154 | fYear = Integer.valueOf(year);
155 | }
156 | String month = getGroup(matcher, 2, 5);
157 | if(month !=null ){
158 | fMonth = Integer.valueOf(month);
159 | }
160 | String day = getGroup(matcher, 3);
161 | if(day !=null ){
162 | fDay = Integer.valueOf(day);
163 | }
164 | }
165 | else {
166 | throw new DateTimeParser.UnknownDateTimeFormat("Unexpected format for date:" + aDate);
167 | }
168 | }
169 |
170 | private String getGroup(Matcher aMatcher, int... aGroupIds){
171 | String result = null;
172 | for(int id: aGroupIds){
173 | result = aMatcher.group(id);
174 | if(result!=null) break;
175 | }
176 | return result;
177 | }
178 |
179 | private void parseTime(String aTime) {
180 | Matcher matcher = TIME.matcher(aTime);
181 | if (matcher.matches()){
182 | String hour = getGroup(matcher, 1, 5, 8, 10);
183 | if(hour !=null ){
184 | fHour = Integer.valueOf(hour);
185 | }
186 | String minute = getGroup(matcher, 2, 6, 9);
187 | if(minute !=null ){
188 | fMinute = Integer.valueOf(minute);
189 | }
190 | String second = getGroup(matcher, 3, 7);
191 | if(second !=null ){
192 | fSecond = Integer.valueOf(second);
193 | }
194 | String decimalSeconds = getGroup(matcher, 4);
195 | if(decimalSeconds !=null ){
196 | fNanosecond = Integer.valueOf(convertToNanoseconds(decimalSeconds));
197 | }
198 | }
199 | else {
200 | throw new DateTimeParser.UnknownDateTimeFormat("Unexpected format for time:" + aTime);
201 | }
202 | }
203 |
204 | /**
205 | Convert any number of decimals (1..9) into the form it would have taken if nanos had been used,
206 | by adding any 0's to the right side.
207 | */
208 | private String convertToNanoseconds(String aDecimalSeconds){
209 | StringBuilder result = new StringBuilder(aDecimalSeconds);
210 | while( result.length( ) < NUM_DIGITS ){
211 | result.append("0");
212 | }
213 | return result.toString();
214 | }
215 | }
216 |
217 |
218 |
219 |
220 |
--------------------------------------------------------------------------------
/docs/javadoc/hirondelle/date4j/DateTime.Unit.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
32 |
80 |
81 |
82 |
83 |
33 |
51 |
52 |
34 |
35 |
47 |
36 |
46 |
37 |
45 | Overview
38 | Package
39 | Class
40 | Tree
41 | Deprecated
42 | Index
43 | Help
44 |
48 | Version 1.5.1
49 |
50 |
53 |
73 |
54 | PREV CLASS
55 | NEXT CLASS
56 |
57 | FRAMES
58 | NO FRAMES
59 |
66 |
69 |
70 |
71 |
72 |
74 |
79 |
75 | SUMMARY: NESTED | ENUM CONSTANTS | FIELD | METHOD
76 |
77 | DETAIL: ENUM CONSTANTS | FIELD | METHOD
78 |
84 |
85 |
86 |
87 | hirondelle.date4j
88 |
90 |
89 | Enum DateTime.Unit
91 | Object
92 |
95 |
Enum<DateTime.Unit>
93 |
hirondelle.date4j.DateTime.Unit
94 |
96 |
98 |
99 |
101 |
102 |
103 |
104 |
105 |
106 | public static enum DateTime.Unit
112 |
113 |
118 |
165 |
166 |
167 |
168 |
169 |
119 |
122 |
120 | Enum Constant Summary
121 |
123 |
128 |
127 | DAY
124 |
125 |
126 |
129 |
134 |
133 | HOUR
130 |
131 |
132 |
135 |
140 |
139 | MINUTE
136 |
137 |
138 |
141 |
146 |
145 | MONTH
142 |
143 |
144 |
147 |
152 |
151 | NANOSECONDS
148 |
149 |
150 |
153 |
158 |
157 | SECOND
154 |
155 |
156 |
159 |
164 |
163 | YEAR
160 |
161 |
162 |
170 |
192 |
193 |
171 |
174 |
172 | Method Summary
173 |
175 |
182 |
176 |
177 | static DateTime.Unit
181 | valueOf(String name)
178 |
179 |
180 | Returns the enum constant of this type with the specified name.
183 |
191 |
184 |
185 | static DateTime.Unit[]
190 | values()
186 |
187 |
188 | Returns an array containing the constants of this enum type, in
189 | the order they're declared.
194 |
201 |
202 |
195 |
197 | Methods inherited from class Enum
196 |
198 |
200 |
199 | clone, compareTo, equals, getDeclaringClass, hashCode, name, ordinal, toString, valueOf
203 |
210 |
211 |
204 |
206 | Methods inherited from class Object
205 |
207 |
209 |
208 | finalize, getClass, notify, notifyAll, wait, wait, wait
217 |
222 |
223 |
218 |
221 |
219 | Enum Constant Detail
220 |
224 | YEAR
225 |
226 | public static final DateTime.Unit YEAR
227 |
228 |
231 |
229 |
230 |
232 |
233 |
234 | MONTH
235 |
236 | public static final DateTime.Unit MONTH
237 |
238 |
241 |
239 |
240 |
242 |
243 |
244 | DAY
245 |
246 | public static final DateTime.Unit DAY
247 |
248 |
251 |
249 |
250 |
252 |
253 |
254 | HOUR
255 |
256 | public static final DateTime.Unit HOUR
257 |
258 |
261 |
259 |
260 |
262 |
263 |
264 | MINUTE
265 |
266 | public static final DateTime.Unit MINUTE
267 |
268 |
271 |
269 |
270 |
272 |
273 |
274 | SECOND
275 |
276 | public static final DateTime.Unit SECOND
277 |
278 |
281 |
279 |
280 |
282 |
283 |
284 | NANOSECONDS
285 |
286 | public static final DateTime.Unit NANOSECONDS
287 |
288 |
291 |
292 |
293 |
294 |
295 |
289 |
290 |
296 |
301 |
302 |
297 |
300 |
298 | Method Detail
299 |
303 | values
304 |
305 | public static final DateTime.Unit[] values()
306 |
307 |
321 |
311 | for(DateTime.Unit c : DateTime.Unit.values())
312 | System.out.println(c);
313 |
314 |
316 |
317 |
319 |
322 |
323 |
324 | valueOf
325 |
326 | public static DateTime.Unit valueOf(String name)
327 |
328 |
341 |
342 |
334 |
339 | name - the name of the enum constant to be returned.
335 | IllegalArgumentException - if this enum type has no constant
338 | with the specified name
343 |
344 |
345 |
346 |
347 |
348 |
349 |
397 |
398 |
399 |
400 |
350 |
368 |
369 |
351 |
352 |
364 |
353 |
363 |
354 |
362 | Overview
355 | Package
356 | Class
357 | Tree
358 | Deprecated
359 | Index
360 | Help
361 |
365 | Version 1.5.1
366 |
367 |
370 |
390 |
371 | PREV CLASS
372 | NEXT CLASS
373 |
374 | FRAMES
375 | NO FRAMES
376 |
383 |
386 |
387 |
388 |
389 |
391 |
396 |
392 | SUMMARY: NESTED | ENUM CONSTANTS | FIELD | METHOD
393 |
394 | DETAIL: ENUM CONSTANTS | FIELD | METHOD
395 |
401 | Copyright Hirondelle Systems. Published November 19, 2013
402 |
403 |
404 |
--------------------------------------------------------------------------------