15
15
*/
16
16
package org .culturegraph .mf .morph .functions ;
17
17
18
- import java .text .ParseException ;
19
18
import java .text .SimpleDateFormat ;
19
+ import java .util .Calendar ;
20
20
import java .util .Collections ;
21
- import java .util .Date ;
21
+ import java .util .GregorianCalendar ;
22
22
import java .util .HashSet ;
23
23
import java .util .Locale ;
24
24
import java .util .Set ;
27
27
28
28
/**
29
29
* Format date/time strings in Metamorph. By default the input format is
30
- * dd.MM.yyyy and the output format is dd. MMMM yyyy.
31
- *
30
+ * dd.MM.yyyy and the output format is {@link java.text.DateFormat.Field#LONG}.
31
+ * <br/>
32
+ * The Attribute removeLeadingZeros will remove all leading zeros from all
33
+ * numbers in the output date.
34
+ * <br/>
35
+ * The attribute era is used to specify if the date is BC or AD. Default
36
+ * value is AUTO. To understand that, three short examples:
37
+ * <ul><li>Input: 20.07.356 (era=BC)</li>
38
+ * <li>Output (German location): 20. Juli 0356 v. Chr.</li>
39
+ * <ul><li>Input: 20.07.356 (era=AD,removeLeadingZeros=true)</li>
40
+ * <li>Output (German location): 20. Juli 356</li>
41
+ * <li>Input: 20.07.-356 (era=AUTO)</li>
42
+ * <li>Output (German location): 20. Juli 0357 v. Chr. (there is NO year 0;
43
+ * see ISO 8601, Proleptic Gregorian Calendar)</li></ul>
44
+ * <p/>
32
45
* Examples of using this function in Metamorph:
33
- * <ul>
34
- * <li>Default date format: <code><dateformat /></code></li>
35
- * <li>Read ISO-dates and generate German style dates:
36
- * <code><dateformat inputformat="yyyy-MM-dd" outputformat="dd.MM.yyyy" /></code></li>
46
+ * <ul><li>Default date format: <code><dateformat /></code></li>
47
+ * <li>Read ISO-dates and generate German style dates:
48
+ * <code><dateformat inputformat="yyyy-MM-dd" outputformat="dd.MM.yyyy" /></code></li>
37
49
* </ul>
38
50
*
39
51
* @author Michael Büchner
@@ -42,11 +54,15 @@ public class DateFormat extends AbstractSimpleStatelessFunction {
42
54
43
55
public static final String DEFAULT_INPUT_FORMAT = "dd.MM.yyyy" ;
44
56
public static final DateFormats DEFAULT_OUTPUT_FORMAT = DateFormats .LONG ;
57
+ public static final boolean DEFAULT_REMOVE_LEADING_ZEROS = false ;
58
+ public static final Era DEFAULT_ERA = Era .AUTO ;
45
59
46
60
private static final Set <String > SUPPORTED_LANGUAGES ;
47
61
48
62
private String inputFormat = DEFAULT_INPUT_FORMAT ;
49
63
private DateFormats outputFormat = DEFAULT_OUTPUT_FORMAT ;
64
+ private Era era = DEFAULT_ERA ;
65
+ private boolean removeLeadingZeros = DEFAULT_REMOVE_LEADING_ZEROS ;
50
66
private Locale outputLocale = Locale .getDefault ();
51
67
52
68
/**
@@ -73,6 +89,29 @@ int getFormatId() {
73
89
74
90
}
75
91
92
+ /**
93
+ * Supported eras (basically AUTO, AD and BC). Maps to
94
+ * {@link java.util.GregorianCalendar}.
95
+ *
96
+ * @author Michael Büchner
97
+ */
98
+ public enum Era {
99
+ AD (GregorianCalendar .AD ),
100
+ BC (GregorianCalendar .BC ),
101
+ AUTO (-1 );
102
+
103
+ private final int eraId ;
104
+
105
+ Era (final int eraId ) {
106
+ this .eraId = eraId ;
107
+ }
108
+
109
+ int getEraId () {
110
+ return eraId ;
111
+ }
112
+
113
+ }
114
+
76
115
static {
77
116
final Set <String > set = new HashSet <String >();
78
117
Collections .addAll (set , Locale .getISOLanguages ());
@@ -81,15 +120,34 @@ int getFormatId() {
81
120
82
121
@ Override
83
122
public final String process (final String value ) {
84
- String result = value ;
123
+ String result ;
85
124
try {
86
- final java .text .DateFormat inputDateFormat = new SimpleDateFormat (inputFormat );
87
- final Date date = inputDateFormat .parse (value );
88
- result = java .text .DateFormat .getDateInstance (outputFormat .getFormatId (), outputLocale ).format (date );
125
+ final Calendar c = Calendar .getInstance ();
126
+ final SimpleDateFormat sdf = new SimpleDateFormat (inputFormat );
127
+ c .setTime (sdf .parse (value ));
128
+ if (era == Era .BC ) {
129
+ c .set (Calendar .ERA , GregorianCalendar .BC );
130
+ } else if (era == Era .AD ) {
131
+ c .set (Calendar .ERA , GregorianCalendar .AD );
132
+ }
133
+
134
+ final SimpleDateFormat sdfp = (SimpleDateFormat ) java .text .DateFormat .getDateInstance (outputFormat .getFormatId (), outputLocale );
135
+ String p = sdfp .toPattern ();
136
+ if (c .get (Calendar .ERA ) == GregorianCalendar .BC ) {
137
+ p = p .replace ("yyyy" , "yyyy G" );
138
+ }
139
+
140
+ final SimpleDateFormat sdfo = new SimpleDateFormat (p , outputLocale );
141
+ result = sdfo .format (c .getTime ());
142
+
143
+ if (removeLeadingZeros ) {
144
+ result = result .replaceAll ("([0]{1,})([0-9]{1,})" , "$2" );
145
+ }
146
+
89
147
} catch (final IllegalArgumentException e ) {
90
148
throw new MorphDefException ("The date/time format is not supported." , e );
91
- } catch (final ParseException e ) {
92
- // Nothing to do
149
+ } catch (final Exception e ) {
150
+ result = value ;
93
151
}
94
152
return result ;
95
153
}
@@ -102,11 +160,18 @@ public final void setOutputFormat(final DateFormats outputFormat) {
102
160
this .outputFormat = outputFormat ;
103
161
}
104
162
163
+ public final void setEra (final Era era ) {
164
+ this .era = era ;
165
+ }
166
+
167
+ public final void setRemoveLeadingZeros (final boolean removeLeadingZeros ) {
168
+ this .removeLeadingZeros = removeLeadingZeros ;
169
+ }
170
+
105
171
public final void setLanguage (final String language ) {
106
172
if (!SUPPORTED_LANGUAGES .contains (language )) {
107
173
throw new MorphDefException ("Language '" + language + "' not supported." );
108
174
}
109
175
this .outputLocale = new Locale (language );
110
176
}
111
-
112
- }
177
+ }
0 commit comments