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 }