Time class, carry, don't understand how it works exactly

I need help understanding how the pre() function in this Time class works.

Edit: I think maybe I have it, does this seem sound? So far it seems to be working.

The thing I don’t like about this is that I made it work by just dividing milli / 100 and then setting the value of milli %= 100. It does get the tenths, but then milli is no longer truly the value of milliseconds, so when I use this in my Time class, anywhere where milli is used, such as getting angles for smooth clock hand rotations, it’s no longer correct.

Where I am really stuck is how to add the ability to get 1/10sec in-line with this code without affecting the value of milli from one loop to the next.

I’ve updated the code with comments about my understanding of how this works, and which parts I don’t understand.


int lastT, deltaT, carry, milli, hundredths, tenths, sec, min, hr;
String carry100msStr, carry10msStr, carry60secStr, carry60minStr;
void setup() {
   size(400, 600);
   
   lastT = millis();
   milli = 0;
   hundredths = 0;
   tenths = 0;
   sec = second();
   min = minute();
   hr = hour();
}

void draw() {
   background(127);
   
   int rightNow = millis();
   deltaT = rightNow - lastT; 
   lastT = rightNow;
   milli += deltaT; // get the baseUnit count i.e. "milli"
   carry = 0;
   
   // the baseUnit can be as high as 1000
   // the next unit is tenths, and we need just 100 baseUnits for one "tenth"
   // divide the baseUnit count by how many you need for the next unit: floor(milli / 100)
   // if there is not enough yet, this will be '0'
   // if there are enough baseUnits so far, carry 1
   carry = floor(milli / 100);
   
   // not sure how to describe this
   // but I see if I don't use "milli %= 1000" then milli will not count properly on the next loop
   // and if I do use "milli %= 1000" then it also fails but I don't know why. 
   milli %= 1000;
   
   // add "1" or "0" to the next unit, "tenths"
   tenths += carry;
   
   // need 10 of these before incrementing the next unit, "sec"
   carry = floor(tenths / 10);
   
   // not sure how to describe this
   tenths %= 10;
   
   // add "1" or "0" to the next unit, "sec"
   sec += carry;
   
   // need 60 of these before incrementing the next unit, "min"
   carry = floor(sec / 60); 
   
   // not sure how to describe this
   sec %= 60;
   
   // add "1" or "0" to the next unit, "min"
   min += carry;
   
   // need 60 of these before incrementing the next unit, "hr"
   carry = floor(min / 60);
   
   // not sure how to describe this
   min %= 60;
   
   // add "1" or "0" to the next unit, "hr"
   hr += carry;
   
   // not sure how to describe this
   hr %= 24;
   
   String milliStr = nf(milli, 2) + "  milli";
   String tenthsStr = nf(tenths, 1) + " tenths";
   String secStr = nf(sec, 2) + " seconds";
   String minStr = nf(min, 2) + " minutes";
   String hrStr = nf(hr, 2) + " hr";
   
   String[] list = {
      
      milliStr, 
      tenthsStr,
      secStr,
      minStr, 
      hrStr
      
   };
   
   showTextArrayLeft(list);
}

void showTextArrayLeft(String[] strings) {
   
   float textH = 18;
   //textFont(mono);
   textSize(textH);
   textAlign(LEFT, TOP);
   fill(0);
   for (int i=0; i<strings.length; i++) {
      text(strings[i], 5, 5 + i * textH);
   }
}
Previous question

I feel like I can follow the logic and it makes sense, but I have been trying to interpolate a way to include a value for tenths of a second in line with the existing logic and I just don’t understand why it’s not working, so I guess I have to admit I do t really understand why it works.
Could someone please comment on the class pre() function and show me how I would add an extra step to get the tenths of a second in between milli and second, and tell me why my attempt is not working? I would really appreciate it.
In this sketch I’m not actually using the Time class, I pulled out the parts to just work in the draw() loop.

Previous code
int lastT, deltaT, carry, milli, tenths, sec;
void setup() {
   size(400, 600);
   
   lastT = millis();
   milli = 0;
   tenths = 0;
   sec = second();
}

void draw() {
   background(127);
   
   int rightNow = millis();
   deltaT = rightNow - lastT; 
   lastT = rightNow;
   milli += deltaT;
   carry = 0;
   
   tenths = floor(milli / 100);
   String tenthsStr1 = nf(tenths, 1);
   
   carry = floor(tenths / 10);
   String carryStr = nf(carry, 1);
   
   tenths %= 10;
   String tenthsStr2 = nf(tenths, 1);
   
   sec += carry;
   sec %= 60;
   
   String secStr = nf(sec, 2);
   
   String[] list = {
      
      tenthsStr1,
      tenthsStr2,
      carryStr,
      secStr
      
   };
   
   showTextArrayLeft(list);
}

void showTextArrayLeft(String[] strings) {
   
   float textH = 18;
   //textFont(mono);
   textSize(textH);
   textAlign(LEFT, TOP);
   fill(0);
   for (int i=0; i<strings.length; i++) {
      text(strings[i], 5, 5 + i * textH);
   }
}

public class Time {
   private int lastT;
   private int deltaT;
   private int hour, minute, second, tenth, milli;
   
   private final float ANGLE_OFFSET = - PI /2;
   
   private final float ANGLE_HOUR = TWO_PI / 12;
   private final float ANGLE_MINUTE = TWO_PI / 60;
   private final float ANGLE_SECOND = TWO_PI / 60;
   
   Time(int h, int m, int s) {
      hour = h;
      minute = m;
      second = s;
      tenth = 0;
      milli = 0;
      lastT = millis();
      deltaT = 0;
   }
   
   public void pre() {
      // Get the elapsed time since the last draw method
      int carry = 0;
      int now = millis();
      deltaT = now - lastT; 
      lastT = now;
      milli += deltaT;
      
      carry = floor(milli / 1000); // integer division
      milli %= 1000;
      
      tenth = floor(milli / 100);
      
      second += carry;
      carry = floor(second / 60); // integer division
      second %= 60;
      
      minute += carry;
      carry = floor(minute / 60); // integer division
      minute %= 60;
      
      hour += carry;
      hour %= 24;
   }
   
   int getHour() {
      return hour;
   }
   
   float getHourHandAngle() {
      float t = (hour % 12) + (minute /  60f) + (second / 3600f) + (milli/ 3600000f);
      return t * ANGLE_HOUR + ANGLE_OFFSET;
   }
   
   int getMinute() {
      return minute;
   }
   
   float getMinuteHandAngle() {
      float t = minute + (second / 60f) + (milli / 60000f);
      return t * ANGLE_MINUTE + ANGLE_OFFSET;
   }
   
   int getSecond() {
      return second;
   }
   
   float getSecondHandAngle() {
      float t = second + (milli / 1000f);
      return t * ANGLE_SECOND + ANGLE_OFFSET;
   }
   
   int getTenth() {
      return tenth;
   }
   
   int getMilli() {
      return milli;
   }
   
   public String toString() {
      return getHour() + ":" + getMinute() + ":" + getSecond() + "." + milli;
   }
}
1 Like

generally you could do the date / time by

read: date time at start of program

and from then on use the millis() ( counting from start )
to make your own TIME.
and there are many examples…

if you not need a very exact way / just a divider of the system seconds / into msec
you could use the millis Of This Second ( with a ERROR of possible 1/60= 17 msec )

long lastmillis; //______________________ memory of millis of last draw loop
int lastmillisOfSec; //__________________ memory of millis since last sec change
int lastsec; //__________________________ memory of last sec to get the change of sec. ( ERROR by 'dt' WITH 60 FPS / 17msec )

void setup(){
  size(450,100);
  textSize(20);
}

void draw(){
  background(200,200,0);
  fill(0);
  text(nows(),10,20);
}

String nows() {
  long tt = millis();
  long dt = tt - lastmillis;
  lastmillisOfSec +=dt;
  int sec = second();
  if ( sec != lastsec ) { //_____________ new second / reset sec millis
     lastmillisOfSec = 0; //_____________ this can be 'dt' millis late
     lastsec = sec;
  }
  lastmillis = tt; //____________________ last draw run
  String thismillis = nf(lastmillisOfSec,3);
  return ""+year()+"_"+nf(month(), 2)+"_"+nf(day(), 2)+" "+nf(hour(), 2)+":"+nf(minute(), 2)+":"+nf(second(), 2)+"."+thismillis+
  "\n dt "+dt+" tt "+tt+" _ "+thismillis.charAt(0)+" _ "+thismillis.charAt(1)+" _ "+thismillis.charAt(2);
}

1 Like

I’m mostly interested in learning how to make the algorithm do what I want it to do, or understanding it well enough to know if it can’t. The idea of taking parts away and carrying some to the next part looks like a tree of dividing a number into separate parts, and I want to understand how to add more branches without breaking the way it works.

1 Like