These compasses are held by an entity starting at X=0, Z=1 (assuming 0,0 is spawn) facing south, spinning at 1°/tick, and moving circularly around the spawn point at 0.1 radian/tick.
Why spinning and moving? Just illustrating that the compass breaks due to those two actions. The broken compass hits points where it spins, and the specific time depends on the entity yaw and angle to spawn.
Like the clock, this was solved by running key values through the positiveModulo function. I also copied the paradigm from ItemClock, where it works within the range 0-1, instead of the range 0-2pi.
This is the same fix I recommend for MC-83905.
Where ItemCompass.java (MCP 9.28) lines 66-67 reads:
d0 = d0 % (Math.PI * 2D);
d0 = MathHelper.clamp_double(d0, -1.0D, 1.0D);
Replace with:
d0 = (double)MathHelper.positiveModulo( (float)d0 + 0.5F, 1.0F ) - 0.5D;
Where line 70 reads:
this.rotation += this.rota;
Insert after that, the following:
this.rotation = (double)MathHelper.positiveModulo( (float)this.rotation, 1.0F );
Where lines 42-44 read:
d1 = d1 % 360.0D;
double d2 = this.getSpawnToAngle(worldIn, entity);
d0 = Math.PI - ((d1 - 90.0D) * 0.01745329238474369D - d2);
Replace with:
d1 = (double)MathHelper.positiveModulo( (float)d1 / 360F, 1.0F );
double d2 = this.getSpawnToAngle(worldIn, entity) / (Math.PI * 2D);
d0 = 0.5D - ((d1 - 0.25D) - d2);
Where line 48 reads:
d0 = Math.random() * (Math.PI * 2D);
Replace with:
d0 = Math.random();
And finally, where lines 56-57 read:
float f = (float)(d0 / (Math.PI * 2D));
return MathHelper.positiveModulo(f, 1.0F);
Replace with:
return MathHelper.positiveModulo((float)d0, 1.0F);