1 /* 2 * Copyright (c) 2012, 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 /* 27 * Copyright (c) 2012, Stephen Colebourne & Michael Nascimento Santos 28 * 29 * All rights reserved. 30 * 31 * Redistribution and use in source and binary forms, with or without 32 * modification, are permitted provided that the following conditions are met: 33 * 34 * * Redistributions of source code must retain the above copyright notice, 35 * this list of conditions and the following disclaimer. 36 * 37 * * Redistributions in binary form must reproduce the above copyright notice, 38 * this list of conditions and the following disclaimer in the documentation 39 * and/or other materials provided with the distribution. 40 * 41 * * Neither the name of JSR-310 nor the names of its contributors 42 * may be used to endorse or promote products derived from this software 43 * without specific prior written permission. 44 * 45 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 46 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 47 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 48 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR 49 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 50 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 51 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 52 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 53 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 54 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 55 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 56 */ 57 package java.time.chrono; 58 59 import static java.time.temporal.ChronoField.DAY_OF_MONTH; 60 import static java.time.temporal.ChronoField.DAY_OF_YEAR; 61 import static java.time.temporal.ChronoField.ERA; 62 import static java.time.temporal.ChronoField.MONTH_OF_YEAR; 63 import static java.time.temporal.ChronoField.YEAR; 64 import static java.time.temporal.ChronoField.YEAR_OF_ERA; 65 import static java.time.temporal.ChronoUnit.DAYS; 66 import static java.time.temporal.ChronoUnit.MONTHS; 67 68 import java.io.InvalidObjectException; 69 import java.io.ObjectInputStream; 70 import java.io.Serializable; 71 import java.time.Clock; 72 import java.time.DateTimeException; 73 import java.time.Instant; 74 import java.time.LocalDate; 75 import java.time.Year; 76 import java.time.ZoneId; 77 import java.time.format.ResolverStyle; 78 import java.time.temporal.ChronoField; 79 import java.time.temporal.TemporalAccessor; 80 import java.time.temporal.TemporalAdjusters; 81 import java.time.temporal.TemporalField; 82 import java.time.temporal.UnsupportedTemporalTypeException; 83 import java.time.temporal.ValueRange; 84 import java.util.Arrays; 85 import java.util.Calendar; 86 import java.util.List; 87 import java.util.Locale; 88 import java.util.Map; 89 import java.util.TimeZone; 90 91 import sun.util.calendar.CalendarSystem; 92 import sun.util.calendar.LocalGregorianCalendar; 93 94 /** 95 * The Japanese Imperial calendar system. 96 * <p> 97 * This chronology defines the rules of the Japanese Imperial calendar system. 98 * This calendar system is primarily used in Japan. 99 * The Japanese Imperial calendar system is the same as the ISO calendar system 100 * apart from the era-based year numbering. 101 * <p> 102 * Japan introduced the Gregorian calendar starting with Meiji 6. 103 * Only Meiji and later eras are supported; 104 * dates before Meiji 6, January 1 are not supported. 105 * <p> 106 * The supported {@code ChronoField} instances are: 107 * <ul> 108 * <li>{@code DAY_OF_WEEK} 109 * <li>{@code DAY_OF_MONTH} 110 * <li>{@code DAY_OF_YEAR} 111 * <li>{@code EPOCH_DAY} 112 * <li>{@code MONTH_OF_YEAR} 113 * <li>{@code PROLEPTIC_MONTH} 114 * <li>{@code YEAR_OF_ERA} 115 * <li>{@code YEAR} 116 * <li>{@code ERA} 117 * </ul> 118 * 119 * @implSpec 120 * This class is immutable and thread-safe. 121 * 122 * @since 1.8 123 */ 124 public final class JapaneseChronology extends AbstractChronology implements Serializable { 125 126 static final LocalGregorianCalendar JCAL = 127 (LocalGregorianCalendar) CalendarSystem.forName("japanese"); 128 129 // Android-changed: don't use locale to create japanese imperial calendar, as it's not generally 130 // supported on Android. Use Calendar.getJapaneseImperialInstance() instead. See .createCalendar 131 // Locale for creating a JapaneseImpericalCalendar. 132 private static final Locale LOCALE = Locale.forLanguageTag("ja-JP-u-ca-japanese"); 133 createCalendar()134 static Calendar createCalendar() { 135 return Calendar.getJapaneseImperialInstance(TimeZone.getDefault(), LOCALE); 136 } 137 138 /** 139 * Singleton instance for Japanese chronology. 140 */ 141 public static final JapaneseChronology INSTANCE = new JapaneseChronology(); 142 143 /** 144 * Serialization version. 145 */ 146 private static final long serialVersionUID = 459996390165777884L; 147 148 //----------------------------------------------------------------------- 149 /** 150 * Restricted constructor. 151 */ JapaneseChronology()152 private JapaneseChronology() { 153 } 154 155 //----------------------------------------------------------------------- 156 /** 157 * Gets the ID of the chronology - 'Japanese'. 158 * <p> 159 * The ID uniquely identifies the {@code Chronology}. 160 * It can be used to lookup the {@code Chronology} using {@link Chronology#of(String)}. 161 * 162 * @return the chronology ID - 'Japanese' 163 * @see #getCalendarType() 164 */ 165 @Override getId()166 public String getId() { 167 return "Japanese"; 168 } 169 170 /** 171 * Gets the calendar type of the underlying calendar system - 'japanese'. 172 * <p> 173 * The calendar type is an identifier defined by the 174 * <em>Unicode Locale Data Markup Language (LDML)</em> specification. 175 * It can be used to lookup the {@code Chronology} using {@link Chronology#of(String)}. 176 * It can also be used as part of a locale, accessible via 177 * {@link Locale#getUnicodeLocaleType(String)} with the key 'ca'. 178 * 179 * @return the calendar system type - 'japanese' 180 * @see #getId() 181 */ 182 @Override getCalendarType()183 public String getCalendarType() { 184 return "japanese"; 185 } 186 187 //----------------------------------------------------------------------- 188 /** 189 * Obtains a local date in Japanese calendar system from the 190 * era, year-of-era, month-of-year and day-of-month fields. 191 * <p> 192 * The Japanese month and day-of-month are the same as those in the 193 * ISO calendar system. They are not reset when the era changes. 194 * For example: 195 * <pre> 196 * 6th Jan Showa 64 = ISO 1989-01-06 197 * 7th Jan Showa 64 = ISO 1989-01-07 198 * 8th Jan Heisei 1 = ISO 1989-01-08 199 * 9th Jan Heisei 1 = ISO 1989-01-09 200 * </pre> 201 * 202 * @param era the Japanese era, not null 203 * @param yearOfEra the year-of-era 204 * @param month the month-of-year 205 * @param dayOfMonth the day-of-month 206 * @return the Japanese local date, not null 207 * @throws DateTimeException if unable to create the date 208 * @throws ClassCastException if the {@code era} is not a {@code JapaneseEra} 209 */ 210 @Override date(Era era, int yearOfEra, int month, int dayOfMonth)211 public JapaneseDate date(Era era, int yearOfEra, int month, int dayOfMonth) { 212 if (era instanceof JapaneseEra == false) { 213 throw new ClassCastException("Era must be JapaneseEra"); 214 } 215 return JapaneseDate.of((JapaneseEra) era, yearOfEra, month, dayOfMonth); 216 } 217 218 /** 219 * Obtains a local date in Japanese calendar system from the 220 * proleptic-year, month-of-year and day-of-month fields. 221 * <p> 222 * The Japanese proleptic year, month and day-of-month are the same as those 223 * in the ISO calendar system. They are not reset when the era changes. 224 * 225 * @param prolepticYear the proleptic-year 226 * @param month the month-of-year 227 * @param dayOfMonth the day-of-month 228 * @return the Japanese local date, not null 229 * @throws DateTimeException if unable to create the date 230 */ 231 @Override date(int prolepticYear, int month, int dayOfMonth)232 public JapaneseDate date(int prolepticYear, int month, int dayOfMonth) { 233 return new JapaneseDate(LocalDate.of(prolepticYear, month, dayOfMonth)); 234 } 235 236 /** 237 * Obtains a local date in Japanese calendar system from the 238 * era, year-of-era and day-of-year fields. 239 * <p> 240 * The day-of-year in this factory is expressed relative to the start of the year-of-era. 241 * This definition changes the normal meaning of day-of-year only in those years 242 * where the year-of-era is reset to one due to a change in the era. 243 * For example: 244 * <pre> 245 * 6th Jan Showa 64 = day-of-year 6 246 * 7th Jan Showa 64 = day-of-year 7 247 * 8th Jan Heisei 1 = day-of-year 1 248 * 9th Jan Heisei 1 = day-of-year 2 249 * </pre> 250 * 251 * @param era the Japanese era, not null 252 * @param yearOfEra the year-of-era 253 * @param dayOfYear the day-of-year 254 * @return the Japanese local date, not null 255 * @throws DateTimeException if unable to create the date 256 * @throws ClassCastException if the {@code era} is not a {@code JapaneseEra} 257 */ 258 @Override dateYearDay(Era era, int yearOfEra, int dayOfYear)259 public JapaneseDate dateYearDay(Era era, int yearOfEra, int dayOfYear) { 260 return JapaneseDate.ofYearDay((JapaneseEra) era, yearOfEra, dayOfYear); 261 } 262 263 /** 264 * Obtains a local date in Japanese calendar system from the 265 * proleptic-year and day-of-year fields. 266 * <p> 267 * The day-of-year in this factory is expressed relative to the start of the proleptic year. 268 * The Japanese proleptic year and day-of-year are the same as those in the ISO calendar system. 269 * They are not reset when the era changes. 270 * 271 * @param prolepticYear the proleptic-year 272 * @param dayOfYear the day-of-year 273 * @return the Japanese local date, not null 274 * @throws DateTimeException if unable to create the date 275 */ 276 @Override dateYearDay(int prolepticYear, int dayOfYear)277 public JapaneseDate dateYearDay(int prolepticYear, int dayOfYear) { 278 return new JapaneseDate(LocalDate.ofYearDay(prolepticYear, dayOfYear)); 279 } 280 281 /** 282 * Obtains a local date in the Japanese calendar system from the epoch-day. 283 * 284 * @param epochDay the epoch day 285 * @return the Japanese local date, not null 286 * @throws DateTimeException if unable to create the date 287 */ 288 @Override // override with covariant return type dateEpochDay(long epochDay)289 public JapaneseDate dateEpochDay(long epochDay) { 290 return new JapaneseDate(LocalDate.ofEpochDay(epochDay)); 291 } 292 293 @Override dateNow()294 public JapaneseDate dateNow() { 295 return dateNow(Clock.systemDefaultZone()); 296 } 297 298 @Override dateNow(ZoneId zone)299 public JapaneseDate dateNow(ZoneId zone) { 300 return dateNow(Clock.system(zone)); 301 } 302 303 @Override dateNow(Clock clock)304 public JapaneseDate dateNow(Clock clock) { 305 return date(LocalDate.now(clock)); 306 } 307 308 @Override date(TemporalAccessor temporal)309 public JapaneseDate date(TemporalAccessor temporal) { 310 if (temporal instanceof JapaneseDate) { 311 return (JapaneseDate) temporal; 312 } 313 return new JapaneseDate(LocalDate.from(temporal)); 314 } 315 316 @Override 317 @SuppressWarnings("unchecked") localDateTime(TemporalAccessor temporal)318 public ChronoLocalDateTime<JapaneseDate> localDateTime(TemporalAccessor temporal) { 319 return (ChronoLocalDateTime<JapaneseDate>)super.localDateTime(temporal); 320 } 321 322 @Override 323 @SuppressWarnings("unchecked") zonedDateTime(TemporalAccessor temporal)324 public ChronoZonedDateTime<JapaneseDate> zonedDateTime(TemporalAccessor temporal) { 325 return (ChronoZonedDateTime<JapaneseDate>)super.zonedDateTime(temporal); 326 } 327 328 @Override 329 @SuppressWarnings("unchecked") zonedDateTime(Instant instant, ZoneId zone)330 public ChronoZonedDateTime<JapaneseDate> zonedDateTime(Instant instant, ZoneId zone) { 331 return (ChronoZonedDateTime<JapaneseDate>)super.zonedDateTime(instant, zone); 332 } 333 334 //----------------------------------------------------------------------- 335 /** 336 * Checks if the specified year is a leap year. 337 * <p> 338 * Japanese calendar leap years occur exactly in line with ISO leap years. 339 * This method does not validate the year passed in, and only has a 340 * well-defined result for years in the supported range. 341 * 342 * @param prolepticYear the proleptic-year to check, not validated for range 343 * @return true if the year is a leap year 344 */ 345 @Override isLeapYear(long prolepticYear)346 public boolean isLeapYear(long prolepticYear) { 347 return IsoChronology.INSTANCE.isLeapYear(prolepticYear); 348 } 349 350 @Override prolepticYear(Era era, int yearOfEra)351 public int prolepticYear(Era era, int yearOfEra) { 352 if (era instanceof JapaneseEra == false) { 353 throw new ClassCastException("Era must be JapaneseEra"); 354 } 355 356 JapaneseEra jera = (JapaneseEra) era; 357 int gregorianYear = jera.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1; 358 if (yearOfEra == 1) { 359 return gregorianYear; 360 } 361 if (gregorianYear >= Year.MIN_VALUE && gregorianYear <= Year.MAX_VALUE) { 362 LocalGregorianCalendar.Date jdate = JCAL.newCalendarDate(null); 363 jdate.setEra(jera.getPrivateEra()).setDate(yearOfEra, 1, 1); 364 if (JapaneseChronology.JCAL.validate(jdate)) { 365 return gregorianYear; 366 } 367 } 368 throw new DateTimeException("Invalid yearOfEra value"); 369 } 370 371 // Android-changed: Integrate OpenJDK support for Japanese Era Reiwa. 372 /** 373 * Returns the calendar system era object from the given numeric value. 374 * 375 * The numeric values supported by this method are the same as the 376 * numeric values supported by {@link JapaneseEra#of(int)}. 377 * 378 * @param eraValue the era value 379 * @return the Japanese {@code Era} for the given numeric era value 380 * @throws DateTimeException if {@code eraValue} is invalid 381 */ 382 @Override eraOf(int eraValue)383 public JapaneseEra eraOf(int eraValue) { 384 return JapaneseEra.of(eraValue); 385 } 386 387 @Override eras()388 public List<Era> eras() { 389 return Arrays.<Era>asList(JapaneseEra.values()); 390 } 391 getCurrentEra()392 JapaneseEra getCurrentEra() { 393 // Assume that the last JapaneseEra is the current one. 394 JapaneseEra[] eras = JapaneseEra.values(); 395 return eras[eras.length - 1]; 396 } 397 398 //----------------------------------------------------------------------- 399 @Override range(ChronoField field)400 public ValueRange range(ChronoField field) { 401 switch (field) { 402 case ALIGNED_DAY_OF_WEEK_IN_MONTH: 403 case ALIGNED_DAY_OF_WEEK_IN_YEAR: 404 case ALIGNED_WEEK_OF_MONTH: 405 case ALIGNED_WEEK_OF_YEAR: 406 throw new UnsupportedTemporalTypeException("Unsupported field: " + field); 407 case YEAR_OF_ERA: { 408 // Android-changed: use #createCalendar() to create calendar. 409 Calendar jcal = createCalendar(); 410 int startYear = getCurrentEra().getPrivateEra().getSinceDate().getYear(); 411 return ValueRange.of(1, jcal.getGreatestMinimum(Calendar.YEAR), 412 jcal.getLeastMaximum(Calendar.YEAR) + 1, // +1 due to the different definitions 413 Year.MAX_VALUE - startYear); 414 } 415 case DAY_OF_YEAR: { 416 // Android-changed: use #createCalendar() to create calendar. 417 Calendar jcal = createCalendar(); 418 int fieldIndex = Calendar.DAY_OF_YEAR; 419 return ValueRange.of(jcal.getMinimum(fieldIndex), jcal.getGreatestMinimum(fieldIndex), 420 jcal.getLeastMaximum(fieldIndex), jcal.getMaximum(fieldIndex)); 421 } 422 case YEAR: 423 return ValueRange.of(JapaneseDate.MEIJI_6_ISODATE.getYear(), Year.MAX_VALUE); 424 case ERA: 425 return ValueRange.of(JapaneseEra.MEIJI.getValue(), getCurrentEra().getValue()); 426 default: 427 return field.range(); 428 } 429 } 430 431 //----------------------------------------------------------------------- 432 @Override // override for return type resolveDate(Map <TemporalField, Long> fieldValues, ResolverStyle resolverStyle)433 public JapaneseDate resolveDate(Map <TemporalField, Long> fieldValues, ResolverStyle resolverStyle) { 434 return (JapaneseDate) super.resolveDate(fieldValues, resolverStyle); 435 } 436 437 @Override // override for special Japanese behavior resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle)438 ChronoLocalDate resolveYearOfEra(Map<TemporalField, Long> fieldValues, ResolverStyle resolverStyle) { 439 // validate era and year-of-era 440 Long eraLong = fieldValues.get(ERA); 441 JapaneseEra era = null; 442 if (eraLong != null) { 443 era = eraOf(range(ERA).checkValidIntValue(eraLong, ERA)); // always validated 444 } 445 Long yoeLong = fieldValues.get(YEAR_OF_ERA); 446 int yoe = 0; 447 if (yoeLong != null) { 448 yoe = range(YEAR_OF_ERA).checkValidIntValue(yoeLong, YEAR_OF_ERA); // always validated 449 } 450 // if only year-of-era and no year then invent era unless strict 451 if (era == null && yoeLong != null && fieldValues.containsKey(YEAR) == false && resolverStyle != ResolverStyle.STRICT) { 452 era = JapaneseEra.values()[JapaneseEra.values().length - 1]; 453 } 454 // if both present, then try to create date 455 if (yoeLong != null && era != null) { 456 if (fieldValues.containsKey(MONTH_OF_YEAR)) { 457 if (fieldValues.containsKey(DAY_OF_MONTH)) { 458 return resolveYMD(era, yoe, fieldValues, resolverStyle); 459 } 460 } 461 if (fieldValues.containsKey(DAY_OF_YEAR)) { 462 return resolveYD(era, yoe, fieldValues, resolverStyle); 463 } 464 } 465 return null; 466 } 467 prolepticYearLenient(JapaneseEra era, int yearOfEra)468 private int prolepticYearLenient(JapaneseEra era, int yearOfEra) { 469 return era.getPrivateEra().getSinceDate().getYear() + yearOfEra - 1; 470 } 471 resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle)472 private ChronoLocalDate resolveYMD(JapaneseEra era, int yoe, Map<TemporalField,Long> fieldValues, ResolverStyle resolverStyle) { 473 fieldValues.remove(ERA); 474 fieldValues.remove(YEAR_OF_ERA); 475 if (resolverStyle == ResolverStyle.LENIENT) { 476 int y = prolepticYearLenient(era, yoe); 477 long months = Math.subtractExact(fieldValues.remove(MONTH_OF_YEAR), 1); 478 long days = Math.subtractExact(fieldValues.remove(DAY_OF_MONTH), 1); 479 return date(y, 1, 1).plus(months, MONTHS).plus(days, DAYS); 480 } 481 int moy = range(MONTH_OF_YEAR).checkValidIntValue(fieldValues.remove(MONTH_OF_YEAR), MONTH_OF_YEAR); 482 int dom = range(DAY_OF_MONTH).checkValidIntValue(fieldValues.remove(DAY_OF_MONTH), DAY_OF_MONTH); 483 if (resolverStyle == ResolverStyle.SMART) { // previous valid 484 if (yoe < 1) { 485 throw new DateTimeException("Invalid YearOfEra: " + yoe); 486 } 487 int y = prolepticYearLenient(era, yoe); 488 JapaneseDate result; 489 try { 490 result = date(y, moy, dom); 491 } catch (DateTimeException ex) { 492 result = date(y, moy, 1).with(TemporalAdjusters.lastDayOfMonth()); 493 } 494 // handle the era being changed 495 // only allow if the new date is in the same Jan-Dec as the era change 496 // determine by ensuring either original yoe or result yoe is 1 497 if (result.getEra() != era && result.get(YEAR_OF_ERA) > 1 && yoe > 1) { 498 throw new DateTimeException("Invalid YearOfEra for Era: " + era + " " + yoe); 499 } 500 return result; 501 } 502 return date(era, yoe, moy, dom); 503 } 504 resolveYD(JapaneseEra era, int yoe, Map <TemporalField,Long> fieldValues, ResolverStyle resolverStyle)505 private ChronoLocalDate resolveYD(JapaneseEra era, int yoe, Map <TemporalField,Long> fieldValues, ResolverStyle resolverStyle) { 506 fieldValues.remove(ERA); 507 fieldValues.remove(YEAR_OF_ERA); 508 if (resolverStyle == ResolverStyle.LENIENT) { 509 int y = prolepticYearLenient(era, yoe); 510 long days = Math.subtractExact(fieldValues.remove(DAY_OF_YEAR), 1); 511 return dateYearDay(y, 1).plus(days, DAYS); 512 } 513 int doy = range(DAY_OF_YEAR).checkValidIntValue(fieldValues.remove(DAY_OF_YEAR), DAY_OF_YEAR); 514 return dateYearDay(era, yoe, doy); // smart is same as strict 515 } 516 517 //----------------------------------------------------------------------- 518 /** 519 * Writes the Chronology using a 520 * <a href="../../../serialized-form.html#java.time.chrono.Ser">dedicated serialized form</a>. 521 * @serialData 522 * <pre> 523 * out.writeByte(1); // identifies a Chronology 524 * out.writeUTF(getId()); 525 * </pre> 526 * 527 * @return the instance of {@code Ser}, not null 528 */ 529 @Override writeReplace()530 Object writeReplace() { 531 return super.writeReplace(); 532 } 533 534 /** 535 * Defend against malicious streams. 536 * 537 * @param s the stream to read 538 * @throws InvalidObjectException always 539 */ readObject(ObjectInputStream s)540 private void readObject(ObjectInputStream s) throws InvalidObjectException { 541 throw new InvalidObjectException("Deserialization via serialization delegate"); 542 } 543 } 544