Fix circular dependency.

TimeUtils <-> TimestampFactory.

Bug: b/272430478
Test: npm run test:unit:ci && npm run deps_graph:check_cycles
Change-Id: I26497902f42873859a6211ee2a5a8299821b7d44
diff --git a/tools/winscope/src/common/time_utils.ts b/tools/winscope/src/common/time_utils.ts
index 752b33c..30e02a1 100644
--- a/tools/winscope/src/common/time_utils.ts
+++ b/tools/winscope/src/common/time_utils.ts
@@ -139,19 +139,6 @@
     return ts1;
   }
 
-  static addTimezoneOffset(timezone: string, timestampNs: bigint): bigint {
-    const utcDate = new Date(Number(timestampNs / 1000000n));
-    const timezoneDateFormatted = utcDate.toLocaleString('en-US', {
-      timeZone: timezone,
-    });
-    const timezoneDate = new Date(timezoneDateFormatted);
-    const hoursDiff = timezoneDate.getHours() - utcDate.getHours();
-    const minutesDiff = timezoneDate.getMinutes() - utcDate.getMinutes();
-    return (
-      timestampNs + BigInt(hoursDiff * 3.6e12) + BigInt(minutesDiff * 6e10)
-    );
-  }
-
   private static nanosecondsToHumanElapsed(
     timestampNanos: number | bigint,
     hideNs = true,
diff --git a/tools/winscope/src/common/time_utils_test.ts b/tools/winscope/src/common/time_utils_test.ts
index 500fd57..2572999 100644
--- a/tools/winscope/src/common/time_utils_test.ts
+++ b/tools/winscope/src/common/time_utils_test.ts
@@ -461,42 +461,4 @@
     expect(TimeUtils.format(timestamp, true)).toEqual('100ms');
     expect(TimeUtils.format(timestamp)).toEqual('100ms0ns');
   });
-
-  it('addTimezoneOffset for elapsed timestamps', () => {
-    const elapsedTimestampNs = 1000000000000n;
-    expect(
-      TimeUtils.addTimezoneOffset('Europe/London', elapsedTimestampNs),
-    ).toEqual(4600000000000n);
-    expect(
-      TimeUtils.addTimezoneOffset('Europe/Zurich', elapsedTimestampNs),
-    ).toEqual(4600000000000n);
-    expect(
-      TimeUtils.addTimezoneOffset('America/Los_Angeles', elapsedTimestampNs),
-    ).toEqual(58600000000000n);
-    expect(
-      TimeUtils.addTimezoneOffset('Asia/Kolkata', elapsedTimestampNs),
-    ).toEqual(20800000000000n);
-  });
-
-  it('addTimezoneOffset for real timestamps', () => {
-    const realTimestampNs = 1706094750112797658n;
-    expect(
-      TimeUtils.addTimezoneOffset('Europe/London', realTimestampNs),
-    ).toEqual(1706094750112797658n);
-    expect(
-      TimeUtils.addTimezoneOffset('Europe/Zurich', realTimestampNs),
-    ).toEqual(1706098350112797658n);
-    expect(
-      TimeUtils.addTimezoneOffset('America/Los_Angeles', realTimestampNs),
-    ).toEqual(1706065950112797658n);
-    expect(
-      TimeUtils.addTimezoneOffset('Asia/Kolkata', realTimestampNs),
-    ).toEqual(1706114550112797658n);
-  });
-
-  it('addTimezoneOffset throws for invalid timezone', () => {
-    expect(() =>
-      TimeUtils.addTimezoneOffset('Invalid/Timezone', 10n),
-    ).toThrow();
-  });
 });
diff --git a/tools/winscope/src/common/timestamp_factory.ts b/tools/winscope/src/common/timestamp_factory.ts
index f209eb3..d0dd685 100644
--- a/tools/winscope/src/common/timestamp_factory.ts
+++ b/tools/winscope/src/common/timestamp_factory.ts
@@ -15,7 +15,6 @@
  */
 
 import {Timestamp, TimestampType, TimezoneInfo} from './time';
-import {TimeUtils} from './time_utils';
 
 export class TimestampFactory {
   constructor(
@@ -29,7 +28,7 @@
     const valueWithRealtimeOffset = valueNs + (realToElapsedTimeOffsetNs ?? 0n);
     const localNs =
       this.timezoneInfo.timezone !== 'UTC'
-        ? TimeUtils.addTimezoneOffset(
+        ? this.addTimezoneOffset(
             this.timezoneInfo.timezone,
             valueWithRealtimeOffset,
           )
@@ -74,6 +73,19 @@
         throw new Error('Unhandled timestamp type');
     }
   }
+
+  private addTimezoneOffset(timezone: string, timestampNs: bigint): bigint {
+    const utcDate = new Date(Number(timestampNs / 1000000n));
+    const timezoneDateFormatted = utcDate.toLocaleString('en-US', {
+      timeZone: timezone,
+    });
+    const timezoneDate = new Date(timezoneDateFormatted);
+    const hoursDiff = timezoneDate.getHours() - utcDate.getHours();
+    const minutesDiff = timezoneDate.getMinutes() - utcDate.getMinutes();
+    return (
+      timestampNs + BigInt(hoursDiff * 3.6e12) + BigInt(minutesDiff * 6e10)
+    );
+  }
 }
 
 export const NO_TIMEZONE_OFFSET_FACTORY = new TimestampFactory();
diff --git a/tools/winscope/src/common/timestamp_factory_test.ts b/tools/winscope/src/common/timestamp_factory_test.ts
index b69401a..9cd42fb 100644
--- a/tools/winscope/src/common/timestamp_factory_test.ts
+++ b/tools/winscope/src/common/timestamp_factory_test.ts
@@ -138,4 +138,39 @@
       ).toThrow();
     });
   });
+
+  describe('adds correct offset for different timezones', () => {
+    it('creates correct real timestamps for different timezones', () => {
+      const realTimestampNs = 1706094750112797658n;
+      expect(
+        new TimestampFactory({timezone: 'Europe/London', locale: 'en-US'})
+          .makeRealTimestamp(realTimestampNs)
+          .getValueNs(),
+      ).toEqual(1706094750112797658n);
+      expect(
+        new TimestampFactory({timezone: 'Europe/Zurich', locale: 'en-US'})
+          .makeRealTimestamp(realTimestampNs)
+          .getValueNs(),
+      ).toEqual(1706098350112797658n);
+      expect(
+        new TimestampFactory({timezone: 'America/Los_Angeles', locale: 'en-US'})
+          .makeRealTimestamp(realTimestampNs)
+          .getValueNs(),
+      ).toEqual(1706065950112797658n);
+      expect(
+        new TimestampFactory({timezone: 'Asia/Kolkata', locale: 'en-US'})
+          .makeRealTimestamp(realTimestampNs)
+          .getValueNs(),
+      ).toEqual(1706114550112797658n);
+    });
+
+    it('throws error for invalid timezone', () => {
+      expect(() =>
+        new TimestampFactory({
+          timezone: 'Invalid/Timezone',
+          locale: 'en-US',
+        }).makeRealTimestamp(10n),
+      ).toThrow();
+    });
+  });
 });