1 /*
2  * hunt-time: A time library for D programming language.
3  *
4  * Copyright (C) 2015-2018 HuntLabs
5  *
6  * Website: https://www.huntlabs.net/
7  *
8  * Licensed under the Apache-2.0 License.
9  *
10  */
11 
12 module hunt.time.chrono.IsoEra;
13 
14 import hunt.time.Exceptions;
15 import hunt.time.chrono.Era;
16 import hunt.time.chrono.IsoEra;
17 import std.conv;
18 import hunt.time.temporal.TemporalField;
19 import hunt.time.temporal.ChronoField;
20 import hunt.time.Exceptions;
21 import hunt.time.temporal.ValueRange;
22 import hunt.time.temporal.Temporal;
23 import hunt.time.format.TextStyle;
24 // import hunt.time.format.DateTimeFormatterBuilder;
25 // import hunt.time.util.Locale;
26 /**
27  * An era _in the ISO calendar system.
28  * !(p)
29  * The ISO-8601 standard does not define eras.
30  * A definition has therefore been created with two eras - 'Current era' (CE) for
31  * years on or after 0001-01-01 (ISO), and 'Before current era' (BCE) for years before that.
32  *
33  * <table class="striped" style="text-align:left">
34  * <caption style="display:none">ISO years and eras</caption>
35  * !(thead)
36  * !(tr)
37  * <th scope="col">year-of-era</th>
38  * <th scope="col">era</th>
39  * <th scope="col">proleptic-year</th>
40  * </tr>
41  * </thead>
42  * !(tbody)
43  * !(tr)
44  * !(td)2</td>!(td)CE</td><th scope="row">2</th>
45  * </tr>
46  * !(tr)
47  * !(td)1</td>!(td)CE</td><th scope="row">1</th>
48  * </tr>
49  * !(tr)
50  * !(td)1</td>!(td)BCE</td><th scope="row">0</th>
51  * </tr>
52  * !(tr)
53  * !(td)2</td>!(td)BCE</td><th scope="row">-1</th>
54  * </tr>
55  * </tbody>
56  * </table>
57  * !(p)
58  * !(b)Do not use {@code ordinal()} to obtain the numeric representation of {@code IsoEra}.
59  * Use {@code getValue()} instead.</b>
60  *
61  * @implSpec
62  * This is an immutable and thread-safe enum.
63  *
64  * @since 1.8
65  */
66 public class IsoEra : Era {
67 
68     /**
69      * The singleton instance for the era before the current one, 'Before Current Era',
70      * which has the numeric value 0.
71      */
72     static IsoEra BCE;
73     /**
74      * The singleton instance for the current era, 'Current Era',
75      * which has the numeric value 1.
76      */
77     static IsoEra CE;
78 
79     // static this()
80     // {
81     //     BCE = new  IsoEra(0);
82     //     CE = new IsoEra(1);
83     // }
84 
85     private int _ordinal;
86 
87     this(int ordinal)
88     {
89         _ordinal = ordinal;
90     }
91     //-----------------------------------------------------------------------
92     /**
93      * Obtains an instance of {@code IsoEra} from an {@code int} value.
94      * !(p)
95      * {@code IsoEra} is an enum representing the ISO eras of BCE/CE.
96      * This factory allows the enum to be obtained from the {@code int} value.
97      *
98      * @param isoEra  the BCE/CE value to represent, from 0 (BCE) to 1 (CE)
99      * @return the era singleton, not null
100      * @throws DateTimeException if the value is invalid
101      */
102     public static IsoEra of(int isoEra) {
103         switch (isoEra) {
104             case 0:
105                 return BCE;
106             case 1:
107                 return CE;
108             default:
109                 throw new DateTimeException("Invalid era: " ~ isoEra.to!string);
110         }
111     }
112 
113     //-----------------------------------------------------------------------
114     /**
115      * Gets the numeric era {@code int} value.
116      * !(p)
117      * The era BCE has the value 0, while the era CE has the value 1.
118      *
119      * @return the era value, from 0 (BCE) to 1 (CE)
120      */
121     override
122     public int getValue() {
123         return ordinal();
124     }
125 
126     int ordinal()
127     {
128         return _ordinal;
129     }
130 
131     override
132      bool isSupported(TemporalField field) {
133         if (cast(ChronoField)(field) !is null) {
134             return field == ChronoField.ERA;
135         }
136         return field !is null && field.isSupportedBy(this);
137     }
138 	
139     override  // override for Javadoc
140      ValueRange range(TemporalField field) {
141         return /* TemporalAccessor. */super_range(field);
142     }
143 	
144      ValueRange super_range(TemporalField field)
145     {
146         if (cast(ChronoField)(field) !is null)
147         {
148             if (isSupported(field))
149             {
150                 return field.range();
151             }
152             throw new UnsupportedTemporalTypeException("Unsupported field: " ~ field.toString);
153         }
154         assert(field, "field");
155         return field.rangeRefinedBy(this);
156     }
157 
158      int super_get(TemporalField field)
159     {
160         ValueRange range = range(field);
161         if (range.isIntValue() == false)
162         {
163             throw new UnsupportedTemporalTypeException(
164                     "Invalid field " ~ field.toString ~ " for get() method, use getLong() instead");
165         }
166         long value = getLong(field);
167         if (range.isValidValue(value) == false)
168         {
169             throw new DateTimeException(
170                     "Invalid value for " ~ field.toString ~ " (valid values "
171                     ~ range.toString ~ "): " ~ value.to!string);
172         }
173         return cast(int) value;
174     }
175 
176     override  // override for Javadoc and performance
177      int get(TemporalField field) {
178         if (field == ChronoField.ERA) {
179             return getValue();
180         }
181         return /* TemporalAccessor. */super_get(field);
182     }
183 	
184 	override
185      long getLong(TemporalField field) {
186         if (field == ChronoField.ERA) {
187             return getValue();
188         } else if (cast(ChronoField)(field) !is null) {
189             throw new UnsupportedTemporalTypeException("Unsupported field: " ~ field.toString);
190         }
191         return field.getFrom(this);
192     }
193 	
194 	override
195      Temporal adjustInto(Temporal temporal) {
196         return temporal._with(ChronoField.ERA, getValue());
197     }
198 	
199     // override
200 	//  string getDisplayName(TextStyle style, Locale locale) {
201     //     return new DateTimeFormatterBuilder().appendText(ChronoField.ERA, style).toFormatter(locale).format(this);
202     // }
203 
204     override string toString()
205     {
206         return super.toString();
207     }
208 }