chinabugotech/hutool · error · DateException

This is not a mutable object !

Error message

This is not a mutable object !

What it means

Thrown by DateTime.setTime(long) when the DateTime is configured as immutable (mutable == false). By default DateTime is mutable, but calling setMutable(false) or creating an immutable instance makes setTime() a prohibited mutation. The design intent is that immutable DateTime instances must not be altered in place — use offset(), setField(), or other methods that return new instances.

Source

Thrown at hutool-core/src/main/java/cn/hutool/core/date/DateTime.java:432

	 * @return this
	 */
	public DateTime setField(int field, int value) {
		final Calendar calendar = toCalendar();
		calendar.set(field, value);

		DateTime dt = this;
		if (false == mutable) {
			dt = ObjectUtil.clone(this);
		}
		return dt.setTimeInternal(calendar.getTimeInMillis());
	}

	@Override
	public void setTime(long time) {
		if (mutable) {
			super.setTime(time);
		} else {
			throw new DateException("This is not a mutable object !");
		}
	}

	/**
	 * 获得年的部分
	 *
	 * @return 年的部分
	 */
	public int year() {
		return getField(DateField.YEAR);
	}

	/**
	 * 获得当前日期所属季度,从1开始计数<br>
	 *
	 * @return 第几个季度 {@link Quarter}
	 */
	public int quarter() {

View on GitHub (pinned to 8870454b2a)

Solutions

  1. If you need to change the time, use offset() or setField() which respect immutability and return new DateTime instances.
  2. If mutation is required, ensure mutable is true: dateTime.setMutable(true) before calling setTime().
  3. Create a new DateTime with the desired time: new DateTime(millis) instead of setTime() on an existing immutable instance.
  4. When passing DateTime to APIs that call setTime(), wrap it in a plain java.util.Date or ensure it is mutable.

Example fix

// before
DateTime dt = DateUtil.date();
dt.setMutable(false);
dt.setTime(newMillis); // throws DateException

// after
DateTime dt = DateUtil.date();
dt.setMutable(false);
DateTime updated = new DateTime(newMillis);
// or: dt.setMutable(true); dt.setTime(newMillis);
Defensive patterns

Strategy: validation

Validate before calling

if (!dateTime.isMutable()) {
    // use new DateTime or set mutable first
    return new DateTime(newMillis);
}
dateTime.setTime(newMillis);

Type guard

static boolean isMutable(DateTime dt) {
    // check the mutable flag before calling setTime
    return FieldUtil.getFieldValue(dt, "mutable") == Boolean.TRUE;
}

Try / catch

try {
    dateTime.setTime(millis);
} catch (DateException e) {
    // create a new instance instead
    return new DateTime(millis);
}

Prevention

When it happens

Trigger: Creating DateTime with mutable=false (via setMutable(false)) then calling setTime(millis). Passing an immutable DateTime to legacy code or third-party libraries that call setTime() on Date objects (since DateTime extends Date). Deserializing into an immutable DateTime via a framework that uses setTime().

Common situations: Sharing DateTime instances across threads and setting mutable=false for thread safety, then calling setTime() inadvertently. Date-oriented APIs that call setTime() on any java.util.Date subclass. Confusion between offset()/setField() (which handle immutability by cloning) and setTime() (which does not).

Related errors


AI-assisted analysis of chinabugotech/hutool@8870454b2a (2026-08-14). Data as JSON: /api/errors/dfdc8c8ad0129fc4. Report an issue: GitHub.