+
+dcp::Time
+dcp::operator+ (Time a, Time b)
+{
+ Time r;
+
+ /* Make sure we have a common tcr */
+ if (a.tcr != b.tcr) {
+ a.e *= b.tcr;
+ b.e *= a.tcr;
+ r.tcr = a.tcr * b.tcr;
+ } else {
+ r.tcr = a.tcr;
+ }
+
+ r.e = a.e + b.e;
+ if (r.e >= r.tcr) {
+ r.e -= r.tcr;
+ r.s++;
+ }
+
+ r.s += a.s + b.s;
+ if (r.s >= 60) {
+ r.s -= 60;
+ r.m++;
+ }
+
+ r.m += a.m + b.m;
+ if (r.m >= 60) {
+ r.m -= 60;
+ r.h++;
+ }
+
+ r.h += a.h + b.h;
+
+ return r;
+}
+
+dcp::Time
+dcp::operator- (Time a, Time b)
+{
+ Time r;
+
+ /* Make sure we have a common tcr */
+ if (a.tcr != b.tcr) {
+ a.e *= b.tcr;
+ b.e *= a.tcr;
+ r.tcr = a.tcr * b.tcr;
+ } else {
+ r.tcr = a.tcr;
+ }
+
+ r.e = a.e - b.e;
+ if (r.e < 0) {
+ r.e += r.tcr;
+ r.s--;
+ }
+
+ r.s += (a.s - b.s);
+ if (r.s < 0) {
+ r.s += 60;
+ r.m--;
+ }
+
+ r.m += (a.m - b.m);
+ if (r.m < 0) {
+ r.m += 60;
+ r.h--;
+ }
+
+ r.h += (a.h - b.h);
+
+ return r;
+}
+
+float
+dcp::operator/ (Time a, Time const & b)
+{
+ int64_t const at = a.h * 3600 + a.m * 60 + a.s * float (a.e) / a.tcr;
+ int64_t const bt = b.h * 3600 + b.m * 60 + b.s * float (b.e) / b.tcr;
+ return float (at) / bt;
+}
+
+/** @return A string of the form h:m:s:e padded as in 00:00:00:000 */
+string
+Time::as_string () const
+{
+ stringstream str;
+ str << setw(2) << setfill('0') << h << ":"
+ << setw(2) << setfill('0') << m << ":"
+ << setw(2) << setfill('0') << s << ":"
+ << setw(3) << setfill('0') << e;
+ return str.str ();
+}
+
+/** @param tcr_ Timecode rate with which the return value should be counted.
+ * @return the total number of editable units that this time consists of at the specified timecode rate.
+ * For example, as_editable_units (24) returns the total time in frames at 24fps.
+ */
+int64_t
+Time::as_editable_units (int tcr_) const
+{
+ return (int64_t(e) * float (tcr_ / tcr)) + int64_t(s) * tcr_ + int64_t(m) * 60 * tcr_ + int64_t(h) * 60 * 60 * tcr_;
+}
+
+/** @return the total number of seconds that this time consists of */
+double
+Time::as_seconds () const
+{
+ return h * 3600 + m * 60 + s + double(e) / tcr;
+}
+
+/** @param tcr_ New timecode rate.
+ * @return A new Time which is this time at the spcified new timecode rate.
+ */
+Time
+Time::rebase (int tcr_) const
+{
+ return Time (h, m, s, rint (float (e) * tcr_ / tcr), tcr_);
+}