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.temporal.ChronoUnit; 13 14 import hunt.time.Duration; 15 import hunt.time.temporal.TemporalUnit; 16 import hunt.time.temporal.Temporal; 17 import hunt.time.temporal.TemporalField; 18 import hunt.time.temporal.ValueRange; 19 20 import hunt.Exceptions; 21 import hunt.Enum; 22 import hunt.Long; 23 import hunt.time.util.Common; 24 import hunt.util.Comparator; 25 26 import std.concurrency : initOnce; 27 28 /** 29 * A standard set of date periods units. 30 * !(p) 31 * This set of units provide unit-based access to manipulate a date, time or date-time. 32 * The standard set of units can be extended by implementing {@link TemporalUnit}. 33 * !(p) 34 * These units are intended to be applicable _in multiple calendar systems. 35 * For example, most non-ISO calendar systems define units of years, months and days, 36 * just with slightly different rules. 37 * The documentation of each unit explains how it operates. 38 * 39 * @implSpec 40 * This is a final, immutable and thread-safe enum. 41 * 42 * @since 1.8 43 */ 44 class ChronoUnit : TemporalUnit 45 { 46 47 /** 48 * Unit that represents the concept of a nanosecond, the smallest supported unit of time. 49 * For the ISO calendar system, it is equal to the 1,000,000,000th part of the second unit. 50 */ 51 static ChronoUnit NANOS() { 52 __gshared ChronoUnit _NANOS; 53 return initOnce!(_NANOS)(new ChronoUnit("Nanos", 0, Duration.ofNanos(1))); 54 } 55 56 /** 57 * Unit that represents the concept of a microsecond. 58 * For the ISO calendar system, it is equal to the 1,000,000th part of the second unit. 59 */ 60 static ChronoUnit MICROS() { 61 __gshared ChronoUnit _MICROS; 62 return initOnce!(_MICROS)(new ChronoUnit("Micros", 1, Duration.ofNanos(1000))); 63 } 64 65 /** 66 * Unit that represents the concept of a millisecond. 67 * For the ISO calendar system, it is equal to the 1000th part of the second unit. 68 */ 69 static ChronoUnit MILLIS() { 70 __gshared ChronoUnit _MILLIS; 71 return initOnce!(_MILLIS)(new ChronoUnit("Millis", 2, Duration.ofNanos(1000_000))); 72 } 73 74 /** 75 * Unit that represents the concept of a second. 76 * For the ISO calendar system, it is equal to the second _in the SI system 77 * of units, except around a leap-second. 78 */ 79 static ChronoUnit SECONDS() { 80 __gshared ChronoUnit _SECONDS; 81 return initOnce!(_SECONDS)(new ChronoUnit("Seconds", 3, Duration.ofSeconds(1))); 82 } 83 84 /** 85 * Unit that represents the concept of a minute. 86 * For the ISO calendar system, it is equal to 60 seconds. 87 */ 88 static ChronoUnit MINUTES() { 89 __gshared ChronoUnit _MINUTES; 90 return initOnce!(_MINUTES)(new ChronoUnit("Minutes", 4, Duration.ofSeconds(60))); 91 } 92 93 /** 94 * Unit that represents the concept of an hour. 95 * For the ISO calendar system, it is equal to 60 minutes. 96 */ 97 static ChronoUnit HOURS() { 98 __gshared ChronoUnit _HOURS; 99 return initOnce!(_HOURS)(new ChronoUnit("Hours", 5, Duration.ofSeconds(3600))); 100 } 101 102 /** 103 * Unit that represents the concept of half a day, as used _in AM/PM. 104 * For the ISO calendar system, it is equal to 12 hours. 105 */ 106 static ChronoUnit HALF_DAYS() { 107 __gshared ChronoUnit _HALF_DAYS; 108 return initOnce!(_HALF_DAYS)(new ChronoUnit("HalfDays", 6, Duration.ofSeconds(43200))); 109 } 110 111 /** 112 * Unit that represents the concept of a day. 113 * For the ISO calendar system, it is the standard day from midnight to midnight. 114 * The estimated duration of a day is {@code 24 Hours}. 115 * !(p) 116 * When used with other calendar systems it must correspond to the day defined by 117 * the rising and setting of the Sun on Earth. It is not required that days begin 118 * at midnight - when converting between calendar systems, the date should be 119 * equivalent at midday. 120 */ 121 static ChronoUnit DAYS() { 122 __gshared ChronoUnit _DAYS; 123 return initOnce!(_DAYS)(new ChronoUnit("Days", 7, Duration.ofSeconds(86400))); 124 } 125 126 /** 127 * Unit that represents the concept of a week. 128 * For the ISO calendar system, it is equal to 7 days. 129 * !(p) 130 * When used with other calendar systems it must correspond to an integral number of days. 131 */ 132 static ChronoUnit WEEKS() { 133 __gshared ChronoUnit _WEEKS; 134 return initOnce!(_WEEKS)(new ChronoUnit("Weeks", 8, Duration.ofSeconds(7 * 86400L))); 135 } 136 137 /** 138 * Unit that represents the concept of a month. 139 * For the ISO calendar system, the length of the month varies by month-of-year. 140 * The estimated duration of a month is one twelfth of {@code 365.2425 Days}. 141 * !(p) 142 * When used with other calendar systems it must correspond to an integral number of days. 143 */ 144 static ChronoUnit MONTHS() { 145 __gshared ChronoUnit _MONTHS; 146 return initOnce!(_MONTHS)(new ChronoUnit("Months", 9, Duration.ofSeconds(31556952L / 12))); 147 } 148 149 /** 150 * Unit that represents the concept of a year. 151 * For the ISO calendar system, it is equal to 12 months. 152 * The estimated duration of a year is {@code 365.2425 Days}. 153 * !(p) 154 * When used with other calendar systems it must correspond to an integral number of days 155 * or months roughly equal to a year defined by the passage of the Earth around the Sun. 156 */ 157 static ChronoUnit YEARS() { 158 __gshared ChronoUnit _YEARS; 159 return initOnce!(_YEARS)(new ChronoUnit("Years", 10, Duration.ofSeconds(31556952L))); 160 } 161 162 /** 163 * Unit that represents the concept of a decade. 164 * For the ISO calendar system, it is equal to 10 years. 165 * !(p) 166 * When used with other calendar systems it must correspond to an integral number of days 167 * and is normally an integral number of years. 168 */ 169 static ChronoUnit DECADES() { 170 __gshared ChronoUnit _DECADES; 171 return initOnce!(_DECADES)(new ChronoUnit("Decades", 11, Duration.ofSeconds(31556952L * 10L))); 172 } 173 174 /** 175 * Unit that represents the concept of a century. 176 * For the ISO calendar system, it is equal to 100 years. 177 * !(p) 178 * When used with other calendar systems it must correspond to an integral number of days 179 * and is normally an integral number of years. 180 */ 181 static ChronoUnit CENTURIES() { 182 __gshared ChronoUnit _CENTURIES; 183 return initOnce!(_CENTURIES)(new ChronoUnit("Centuries", 12, Duration.ofSeconds(31556952L * 100L))); 184 } 185 186 /** 187 * Unit that represents the concept of a millennium. 188 * For the ISO calendar system, it is equal to 1000 years. 189 * !(p) 190 * When used with other calendar systems it must correspond to an integral number of days 191 * and is normally an integral number of years. 192 */ 193 static ChronoUnit MILLENNIA() { 194 __gshared ChronoUnit _MILLENNIA; 195 return initOnce!(_MILLENNIA)(new ChronoUnit("Millennia", 13, Duration.ofSeconds(31556952L * 1000L))); 196 } 197 198 /** 199 * Unit that represents the concept of an era. 200 * The ISO calendar system doesn't have eras thus it is impossible to add 201 * an era to a date or date-time. 202 * The estimated duration of the era is artificially defined as {@code 1,000,000,000 Years}. 203 * !(p) 204 * When used with other calendar systems there are no restrictions on the unit. 205 */ 206 static ChronoUnit ERAS() { 207 __gshared ChronoUnit _ERAS; 208 return initOnce!(_ERAS)(new ChronoUnit("Eras", 14, Duration.ofSeconds(31556952L * 1000_000_000L))); 209 } 210 211 /** 212 * Artificial unit that represents the concept of forever. 213 * This is primarily used with {@link TemporalField} to represent unbounded fields 214 * such as the year or era. 215 * The estimated duration of this unit is artificially defined as the largest duration 216 * supported by {@link Duration}. 217 */ 218 static ChronoUnit FOREVER() { 219 __gshared ChronoUnit _FOREVER; 220 return initOnce!(_FOREVER)(new ChronoUnit("Forever", 15, Duration.ofSeconds(Long.MAX_VALUE, 999_999_999))); 221 } 222 223 224 private Duration duration; 225 226 protected this(string name, int ordinal, Duration estimatedDuration) 227 { 228 super(name, ordinal); 229 this.duration = estimatedDuration; 230 } 231 232 233 //----------------------------------------------------------------------- 234 /** 235 * Gets the estimated duration of this unit _in the ISO calendar system. 236 * !(p) 237 * All of the units _in this class have an estimated duration. 238 * Days vary due to daylight saving time, while months have different lengths. 239 * 240 * @return the estimated duration of this unit, not null 241 */ 242 override Duration getDuration() 243 { 244 return duration; 245 } 246 247 /** 248 * Checks if the duration of the unit is an estimate. 249 * !(p) 250 * All time units _in this class are considered to be accurate, while all date 251 * units _in this class are considered to be estimated. 252 * !(p) 253 * This definition ignores leap seconds, but considers that Days vary due to 254 * daylight saving time and months have different lengths. 255 * 256 * @return true if the duration is estimated, false if accurate 257 */ 258 override bool isDurationEstimated() 259 { 260 return this.opCmp(DAYS) >= 0; 261 } 262 263 //----------------------------------------------------------------------- 264 /** 265 * Checks if this unit is a date unit. 266 * !(p) 267 * All units from days to eras inclusive are date-based. 268 * Time-based units and {@code FOREVER} return false. 269 * 270 * @return true if a date unit, false if a time unit 271 */ 272 override bool isDateBased() 273 { 274 return this.opCmp(DAYS) >= 0 && this != FOREVER; 275 } 276 277 /** 278 * Checks if this unit is a time unit. 279 * !(p) 280 * All units from nanos to half-days inclusive are time-based. 281 * Date-based units and {@code FOREVER} return false. 282 * 283 * @return true if a time unit, false if a date unit 284 */ 285 override bool isTimeBased() 286 { 287 return this.opCmp(DAYS) < 0; 288 } 289 290 //----------------------------------------------------------------------- 291 override bool isSupportedBy(Temporal temporal) 292 { 293 return temporal.isSupported(this); 294 } 295 296 /*@SuppressWarnings("unchecked")*/ 297 override Temporal addTo(Temporal temporal, long amount) /* if(is(R : Temporal)) */ 298 { 299 return cast(Temporal) temporal.plus(amount, this); 300 } 301 302 //----------------------------------------------------------------------- 303 override long between(Temporal temporal1Inclusive, Temporal temporal2Exclusive) 304 { 305 return temporal1Inclusive.until(temporal2Exclusive, this); 306 } 307 308 //----------------------------------------------------------------------- 309 // override string toString() 310 // { 311 // return name; 312 // } 313 314 // bool opEquals(ref const ChronoUnit h) nothrow 315 // { 316 // return name == h.name; 317 // } 318 319 // override bool opEquals(Object obj) 320 // { 321 // if (this is obj) 322 // { 323 // return true; 324 // } 325 // if (cast(ChronoUnit)(obj) !is null) 326 // { 327 // ChronoUnit other = cast(ChronoUnit) obj; 328 // return name == other.name; 329 // } 330 // return false; 331 // } 332 333 // int compareTo(ChronoUnit obj) 334 // { 335 // return compare(this.name, obj.name); 336 // } 337 }