Skip to content

Commit 3a7603a

Browse files
runningcodeclaude
andauthored
perf(android): Replace Date with unix timestamp in SentryNanotimeDate (JAVA-533) (#5550)
* perf(android): Replace Date with unix timestamp in SentryNanotimeDate (JAVA-533) SentryNanotimeDate stored a java.util.Date but only ever read its epoch millis. Storing the millis directly avoids a Calendar allocation on every timestamp, which on Android backs every span/transaction timestamp. The default constructor now uses System.currentTimeMillis() instead of DateUtils.getCurrentDateTime() (Calendar with UTC). This is behavior- preserving: the UTC TimeZone only affects calendar field access, not the epoch-millis value the class used. BREAKING: the public SentryNanotimeDate(Date, long) constructor is replaced by SentryNanotimeDate(long unixDate, long nanos). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * changelog * ref(android): Mark SentryNanotimeDate as @ApiStatus.Internal SentryNanotimeDate is the legacy Date+nanoTime precision workaround and is not intended for direct use by consumers. Marking it @ApiStatus.Internal signals this and means the constructor change in this PR is not a public API break per the repo's API policy. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * refactor(sentry): Rename unixDate field to unixDateMillis Name the long field for its unit so it is clear it holds the unix timestamp in milliseconds since the epoch. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * docs(changelog): Reword SentryNanotimeDate entry Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * feat(sentry): Restore deprecated SentryNanotimeDate Date constructor (JAVA-533) The previous change replaced the (Date, long) constructor with a (long, long) constructor, which was a breaking API change. Add the Date constructor back, delegating to the millis-based one, and mark it deprecated to steer callers toward the new constructor. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sentry): Suppress InlineMeSuggester on deprecated constructor (JAVA-533) Error Prone flagged the deprecated (Date, long) constructor as inlineable, failing the build. Suppress the suggestion to match the existing convention in Sentry.java, keeping the constructor available for backwards compatibility. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> * fix(sentry): Suppress JavaUtilDate on deprecated constructor (JAVA-533) Error Prone's JavaUtilDate check flagged date.getTime() in the deprecated constructor, failing the build. Suppress it, matching the existing suppression used elsewhere in this class. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
1 parent 06b0d80 commit 3a7603a

16 files changed

Lines changed: 99 additions & 116 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@
1313
### Improvements
1414

1515
- Reduce boxing to improve performance ([#5523](https://github.com/getsentry/sentry-java/pull/5523), [#5527](https://github.com/getsentry/sentry-java/pull/5527), [#5551](https://github.com/getsentry/sentry-java/pull/5551))
16+
- Replace `Date` with a unix timestamp in `SentryNanotimeDate` to improve performance ([#5550](https://github.com/getsentry/sentry-java/pull/5550))
17+
- `SentryNanotimeDate` is now marked `@ApiStatus.Internal`. A new `(long unixDateMillis, long nanos)` constructor was added, where `unixDateMillis` is milliseconds since the epoch. The existing `(Date, long)` constructor is retained but deprecated.
1618

1719
### Dependencies
1820

sentry-android-core/src/main/java/io/sentry/android/core/ActivityLifecycleIntegration.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@
4545
import java.io.IOException;
4646
import java.lang.ref.WeakReference;
4747
import java.util.Collections;
48-
import java.util.Date;
4948
import java.util.Map;
5049
import java.util.WeakHashMap;
5150
import java.util.concurrent.Future;
@@ -94,7 +93,7 @@ public final class ActivityLifecycleIntegration
9493
private final @NotNull WeakHashMap<Activity, ISpan> ttfdSpanMap = new WeakHashMap<>();
9594
private final @NotNull WeakHashMap<Activity, ActivityLifecycleSpanHelper> activitySpanHelpers =
9695
new WeakHashMap<>();
97-
private @NotNull SentryDate lastPausedTime = new SentryNanotimeDate(new Date(0), 0);
96+
private @NotNull SentryDate lastPausedTime = new SentryNanotimeDate(0, 0);
9897
private @Nullable Future<?> ttfdAutoCloseFuture = null;
9998

10099
// WeakHashMap isn't thread safe but ActivityLifecycleCallbacks is only called from the
@@ -729,7 +728,7 @@ public void onActivityDestroyed(final @NotNull Activity activity) {
729728

730729
private void clear() {
731730
firstActivityCreated = false;
732-
lastPausedTime = new SentryNanotimeDate(new Date(0), 0);
731+
lastPausedTime = new SentryNanotimeDate(0, 0);
733732
activitySpanHelpers.clear();
734733
}
735734

sentry-android-core/src/main/java/io/sentry/android/core/SpanFrameMetricsCollector.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@
1313
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector;
1414
import io.sentry.protocol.MeasurementValue;
1515
import io.sentry.util.AutoClosableReentrantLock;
16-
import java.util.Date;
1716
import java.util.Iterator;
1817
import java.util.SortedSet;
1918
import java.util.TreeSet;
@@ -33,7 +32,7 @@ public class SpanFrameMetricsCollector
3332
// grow indefinitely in case of a long running span
3433
private static final int MAX_FRAMES_COUNT = 3600;
3534
private static final long ONE_SECOND_NANOS = TimeUnit.SECONDS.toNanos(1);
36-
private static final SentryNanotimeDate EMPTY_NANO_TIME = new SentryNanotimeDate(new Date(0), 0);
35+
private static final SentryNanotimeDate EMPTY_NANO_TIME = new SentryNanotimeDate(0, 0);
3736

3837
private final boolean enabled;
3938
protected final @NotNull AutoClosableReentrantLock lock = new AutoClosableReentrantLock();

sentry-android-core/src/test/java/io/sentry/android/core/ActivityLifecycleIntegrationTest.kt

Lines changed: 33 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,6 @@ import io.sentry.protocol.SentryId
4141
import io.sentry.protocol.TransactionNameSource
4242
import io.sentry.test.DeferredExecutorService
4343
import io.sentry.test.getProperty
44-
import java.util.Date
4544
import java.util.concurrent.Future
4645
import java.util.concurrent.TimeUnit
4746
import kotlin.test.AfterTest
@@ -936,7 +935,7 @@ class ActivityLifecycleIntegrationTest {
936935
sut.register(fixture.scopes, fixture.options)
937936
sut.setFirstActivityCreated(false)
938937

939-
val date = SentryNanotimeDate(Date(1), 0)
938+
val date = SentryNanotimeDate(1, 0)
940939
setAppStartTime(date)
941940
fixture.options.dateProvider = SentryDateProvider { date }
942941

@@ -961,7 +960,7 @@ class ActivityLifecycleIntegrationTest {
961960
sut.register(fixture.scopes, fixture.options)
962961
sut.setFirstActivityCreated(false)
963962

964-
val date = SentryNanotimeDate(Date(1), 0)
963+
val date = SentryNanotimeDate(1, 0)
965964
setAppStartTime(date)
966965

967966
val activity = mock<Activity>()
@@ -984,8 +983,8 @@ class ActivityLifecycleIntegrationTest {
984983
sut.register(fixture.scopes, fixture.options)
985984
sut.setFirstActivityCreated(false)
986985

987-
val date = SentryNanotimeDate(Date(1), 0)
988-
val date2 = SentryNanotimeDate(Date(2), 2)
986+
val date = SentryNanotimeDate(1, 0)
987+
val date2 = SentryNanotimeDate(2, 2)
989988
setAppStartTime(date)
990989

991990
val activity = mock<Activity>()
@@ -1011,7 +1010,7 @@ class ActivityLifecycleIntegrationTest {
10111010
val sut = fixture.getSut { it.tracesSampleRate = 1.0 }
10121011
sut.register(fixture.scopes, fixture.options)
10131012
sut.setFirstActivityCreated(true)
1014-
val date = SentryNanotimeDate(Date(1), 0)
1013+
val date = SentryNanotimeDate(1, 0)
10151014
setAppStartTime(date)
10161015

10171016
val activity = mock<Activity>()
@@ -1030,8 +1029,8 @@ class ActivityLifecycleIntegrationTest {
10301029
sut.setFirstActivityCreated(false)
10311030

10321031
// usually set by SentryPerformanceProvider
1033-
val date = SentryNanotimeDate(Date(1), 0)
1034-
val date2 = SentryNanotimeDate(Date(2), 2)
1032+
val date = SentryNanotimeDate(1, 0)
1033+
val date2 = SentryNanotimeDate(2, 2)
10351034

10361035
val activity = mock<Activity>()
10371036
// Activity onCreate date will be used
@@ -1056,7 +1055,7 @@ class ActivityLifecycleIntegrationTest {
10561055
sut.register(fixture.scopes, fixture.options)
10571056

10581057
// usually set by SentryPerformanceProvider
1059-
val date = SentryNanotimeDate(Date(1), 0)
1058+
val date = SentryNanotimeDate(1, 0)
10601059
setAppStartTime(date)
10611060

10621061
val activity = mock<Activity>()
@@ -1080,7 +1079,7 @@ class ActivityLifecycleIntegrationTest {
10801079
sut.register(fixture.scopes, fixture.options)
10811080

10821081
// usually set by SentryPerformanceProvider
1083-
val startDate = SentryNanotimeDate(Date(1), 0)
1082+
val startDate = SentryNanotimeDate(1, 0)
10841083
setAppStartTime(startDate)
10851084
val appStartMetrics = AppStartMetrics.getInstance()
10861085
appStartMetrics.appStartType = AppStartType.WARM
@@ -1113,9 +1112,9 @@ class ActivityLifecycleIntegrationTest {
11131112
it.isEnableStandaloneAppStartTracing = true
11141113
}
11151114
sut.register(fixture.scopes, fixture.options)
1116-
val firstFrameDate = SentryNanotimeDate(Date(1499), 0)
1115+
val firstFrameDate = SentryNanotimeDate(1499, 0)
11171116
fixture.options.dateProvider = SentryDateProvider { firstFrameDate }
1118-
setAppStartTime(SentryNanotimeDate(Date(1), 0))
1117+
setAppStartTime(SentryNanotimeDate(1, 0))
11191118

11201119
val activity = mock<Activity>()
11211120
sut.onActivityPreCreated(activity, fixture.bundle)
@@ -1168,8 +1167,8 @@ class ActivityLifecycleIntegrationTest {
11681167
it.isEnableStandaloneAppStartTracing = true
11691168
}
11701169
sut.register(fixture.scopes, fixture.options)
1171-
val appStartEndDate = SentryNanotimeDate(Date(499), 0)
1172-
setAppStartTime(SentryNanotimeDate(Date(1), 0), appStartEndDate)
1170+
val appStartEndDate = SentryNanotimeDate(499, 0)
1171+
setAppStartTime(SentryNanotimeDate(1, 0), appStartEndDate)
11731172

11741173
val activity = mock<Activity>()
11751174
sut.onActivityPreCreated(activity, fixture.bundle)
@@ -1230,9 +1229,9 @@ class ActivityLifecycleIntegrationTest {
12301229
AppStartMetrics.getInstance().appStartSentryTraceHeader =
12311230
SentryTraceHeader(storedTraceId, SpanId(), true).value
12321231
// headless start ended right before the activity opens
1233-
AppStartMetrics.getInstance().appStartEndTime = SentryNanotimeDate(Date(0), 0)
1232+
AppStartMetrics.getInstance().appStartEndTime = SentryNanotimeDate(0, 0)
12341233
sut.register(fixture.scopes, fixture.options)
1235-
setAppStartTime(date = SentryNanotimeDate(Date(1), 0))
1234+
setAppStartTime(date = SentryNanotimeDate(1, 0))
12361235

12371236
val activity = mock<Activity>()
12381237
sut.onActivityCreated(activity, fixture.bundle)
@@ -1254,9 +1253,9 @@ class ActivityLifecycleIntegrationTest {
12541253
AppStartMetrics.getInstance().appStartSentryTraceHeader =
12551254
SentryTraceHeader(storedTraceId, SpanId(), true).value
12561255
// headless start ended at epoch, but the activity opens more than a minute later
1257-
AppStartMetrics.getInstance().appStartEndTime = SentryNanotimeDate(Date(0), 0)
1256+
AppStartMetrics.getInstance().appStartEndTime = SentryNanotimeDate(0, 0)
12581257
sut.register(fixture.scopes, fixture.options)
1259-
setAppStartTime(date = SentryNanotimeDate(Date(TimeUnit.MINUTES.toMillis(2)), 0))
1258+
setAppStartTime(date = SentryNanotimeDate(TimeUnit.MINUTES.toMillis(2), 0))
12601259

12611260
val activity = mock<Activity>()
12621261
sut.onActivityCreated(activity, fixture.bundle)
@@ -1389,7 +1388,7 @@ class ActivityLifecycleIntegrationTest {
13891388

13901389
// usually done by SentryPerformanceProvider, if disabled it's done by
13911390
// SentryAndroid.init
1392-
val startDate = SentryNanotimeDate(Date(1), 0)
1391+
val startDate = SentryNanotimeDate(1, 0)
13931392
setAppStartTime(startDate)
13941393
AppStartMetrics.getInstance().appStartType = AppStartType.WARM
13951394

@@ -1415,7 +1414,7 @@ class ActivityLifecycleIntegrationTest {
14151414
sut.register(fixture.scopes, fixture.options)
14161415

14171416
// usually done by SentryPerformanceProvider
1418-
val startDate = SentryNanotimeDate(Date(1), 0)
1417+
val startDate = SentryNanotimeDate(1, 0)
14191418
setAppStartTime(startDate)
14201419
AppStartMetrics.getInstance().appStartType = AppStartType.WARM
14211420
AppStartMetrics.getInstance().sdkInitTimeSpan.setStoppedAt(1234)
@@ -1439,7 +1438,7 @@ class ActivityLifecycleIntegrationTest {
14391438
sut.register(fixture.scopes, fixture.options)
14401439

14411440
// usually done by SentryPerformanceProvider
1442-
val startDate = SentryNanotimeDate(Date(1), 0)
1441+
val startDate = SentryNanotimeDate(1, 0)
14431442
setAppStartTime(startDate)
14441443
AppStartMetrics.getInstance().appStartType = AppStartType.WARM
14451444

@@ -1474,7 +1473,7 @@ class ActivityLifecycleIntegrationTest {
14741473
sut.register(fixture.scopes, fixture.options)
14751474
sut.setFirstActivityCreated(true)
14761475

1477-
val date = SentryNanotimeDate(Date(1), 0)
1476+
val date = SentryNanotimeDate(1, 0)
14781477
setAppStartTime()
14791478

14801479
val activity = mock<Activity>()
@@ -1988,14 +1987,14 @@ class ActivityLifecycleIntegrationTest {
19881987
@Test
19891988
fun `When sentry is initialized mid activity lifecycle, last paused time should be used in favor of app start time`() {
19901989
val sut = fixture.getSut(importance = RunningAppProcessInfo.IMPORTANCE_FOREGROUND)
1991-
val now = SentryNanotimeDate(Date(1234), 456)
1990+
val now = SentryNanotimeDate(1234, 456)
19921991

19931992
fixture.options.tracesSampleRate = 1.0
19941993
fixture.options.dateProvider = SentryDateProvider { now }
19951994
sut.register(fixture.scopes, fixture.options)
19961995

19971996
// usually done by SentryPerformanceProvider
1998-
val startDate = SentryNanotimeDate(Date(5678), 910)
1997+
val startDate = SentryNanotimeDate(5678, 910)
19991998
setAppStartTime(startDate)
20001999
AppStartMetrics.getInstance().appStartType = AppStartType.COLD
20012000

@@ -2019,7 +2018,7 @@ class ActivityLifecycleIntegrationTest {
20192018
fixture.options.tracesSampleRate = 1.0
20202019
sut.register(fixture.scopes, fixture.options)
20212020

2022-
val date = SentryNanotimeDate(Date(1), 0)
2021+
val date = SentryNanotimeDate(1, 0)
20232022
setAppStartTime(date)
20242023

20252024
assertTrue(sut.activitySpanHelpers.isEmpty())
@@ -2036,8 +2035,8 @@ class ActivityLifecycleIntegrationTest {
20362035
fun `Creates activity lifecycle spans`() {
20372036
val sut = fixture.getSut()
20382037
fixture.options.tracesSampleRate = 1.0
2039-
val appStartDate = SentryNanotimeDate(Date(1), 0)
2040-
val startDate = SentryNanotimeDate(Date(2), 0)
2038+
val appStartDate = SentryNanotimeDate(1, 0)
2039+
val startDate = SentryNanotimeDate(2, 0)
20412040
val appStartMetrics = AppStartMetrics.getInstance()
20422041
val activity = mock<Activity>()
20432042
fixture.options.dateProvider = SentryDateProvider { startDate }
@@ -2076,7 +2075,7 @@ class ActivityLifecycleIntegrationTest {
20762075
fun `Creates activity lifecycle spans even when no app start span is available`() {
20772076
val sut = fixture.getSut()
20782077
fixture.options.tracesSampleRate = 1.0
2079-
val startDate = SentryNanotimeDate(Date(2), 0)
2078+
val startDate = SentryNanotimeDate(2, 0)
20802079
val appStartMetrics = AppStartMetrics.getInstance()
20812080
val activity = mock<Activity>()
20822081
fixture.options.dateProvider = SentryDateProvider { startDate }
@@ -2134,8 +2133,8 @@ class ActivityLifecycleIntegrationTest {
21342133
fun `Creates activity lifecycle spans on API lower than 29`() {
21352134
val sut = fixture.getSut(apiVersion = Build.VERSION_CODES.P)
21362135
fixture.options.tracesSampleRate = 1.0
2137-
val appStartDate = SentryNanotimeDate(Date(1), 0)
2138-
val startDate = SentryNanotimeDate(Date(2), 0)
2136+
val appStartDate = SentryNanotimeDate(1, 0)
2137+
val startDate = SentryNanotimeDate(2, 0)
21392138
val appStartMetrics = AppStartMetrics.getInstance()
21402139
val activity = mock<Activity>()
21412140
fixture.options.dateProvider = SentryDateProvider { startDate }
@@ -2187,8 +2186,8 @@ class ActivityLifecycleIntegrationTest {
21872186
fun `Does not add activity lifecycle spans when firstActivityCreated is true`() {
21882187
val sut = fixture.getSut()
21892188
fixture.options.tracesSampleRate = 1.0
2190-
val appStartDate = SentryNanotimeDate(Date(1), 0)
2191-
val startDate = SentryNanotimeDate(Date(2), 0)
2189+
val appStartDate = SentryNanotimeDate(1, 0)
2190+
val startDate = SentryNanotimeDate(2, 0)
21922191
val appStartMetrics = AppStartMetrics.getInstance()
21932192
val activity = mock<Activity>()
21942193
fixture.options.dateProvider = SentryDateProvider { startDate }
@@ -2209,7 +2208,7 @@ class ActivityLifecycleIntegrationTest {
22092208
fun `When firstActivityCreated is false and app start span has stopped, restart app start to current date`() {
22102209
val sut = fixture.getSut()
22112210
fixture.options.tracesSampleRate = 1.0
2212-
val appStartDate = SentryNanotimeDate(Date(1), 0)
2211+
val appStartDate = SentryNanotimeDate(1, 0)
22132212
val appStartMetrics = AppStartMetrics.getInstance()
22142213
val activity = mock<Activity>()
22152214
setAppStartTime(appStartDate)
@@ -2290,7 +2289,7 @@ class ActivityLifecycleIntegrationTest {
22902289
}
22912290

22922291
private fun setAppStartTime(
2293-
date: SentryDate = SentryNanotimeDate(Date(1), 0),
2292+
date: SentryDate = SentryNanotimeDate(1, 0),
22942293
stopDate: SentryDate? = null,
22952294
) {
22962295
// set by SentryPerformanceProvider so forcing it here

sentry-android-core/src/test/java/io/sentry/android/core/NetworkBreadcrumbsIntegrationTest.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import android.net.Network
55
import android.net.NetworkCapabilities
66
import android.os.Build
77
import io.sentry.Breadcrumb
8-
import io.sentry.DateUtils
98
import io.sentry.IScopes
109
import io.sentry.ISentryExecutorService
1110
import io.sentry.SentryDateProvider
@@ -54,8 +53,9 @@ class NetworkBreadcrumbsIntegrationTest {
5453
executorService = executor
5554
isEnableNetworkEventBreadcrumbs = enableNetworkEventBreadcrumbs
5655
dateProvider = SentryDateProvider {
57-
val nowNanos = TimeUnit.MILLISECONDS.toNanos(nowMs ?: System.currentTimeMillis())
58-
SentryNanotimeDate(DateUtils.nanosToDate(nowNanos), nowNanos)
56+
val nowMillis = nowMs ?: System.currentTimeMillis()
57+
val nowNanos = TimeUnit.MILLISECONDS.toNanos(nowMillis)
58+
SentryNanotimeDate(nowMillis, nowNanos)
5959
}
6060
}
6161
return NetworkBreadcrumbsIntegration(context, buildInfo)

sentry-android-core/src/test/java/io/sentry/android/core/SpanFrameMetricsCollectorTest.kt

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import io.sentry.SentryNanotimeDate
88
import io.sentry.SpanContext
99
import io.sentry.android.core.internal.util.SentryFrameMetricsCollector
1010
import io.sentry.protocol.MeasurementValue
11-
import java.util.Date
1211
import java.util.UUID
1312
import java.util.concurrent.TimeUnit
1413
import kotlin.test.Test
@@ -50,11 +49,12 @@ class SpanFrameMetricsCollectorTest {
5049
val span = mock<ISpan>()
5150
val spanContext = SpanContext("op.fake")
5251
whenever(span.spanContext).thenReturn(spanContext)
53-
whenever(span.startDate).thenReturn(SentryNanotimeDate(Date(), startTimeStampNanos))
52+
whenever(span.startDate)
53+
.thenReturn(SentryNanotimeDate(System.currentTimeMillis(), startTimeStampNanos))
5454
whenever(span.finishDate)
5555
.thenReturn(
5656
if (endTimeStampNanos != null) {
57-
SentryNanotimeDate(Date(), endTimeStampNanos)
57+
SentryNanotimeDate(System.currentTimeMillis(), endTimeStampNanos)
5858
} else {
5959
null
6060
}
@@ -69,11 +69,12 @@ class SpanFrameMetricsCollectorTest {
6969
val span = mock<ITransaction>()
7070
val spanContext = SpanContext("op.fake")
7171
whenever(span.spanContext).thenReturn(spanContext)
72-
whenever(span.startDate).thenReturn(SentryNanotimeDate(Date(), startTimeStampNanos))
72+
whenever(span.startDate)
73+
.thenReturn(SentryNanotimeDate(System.currentTimeMillis(), startTimeStampNanos))
7374
whenever(span.finishDate)
7475
.thenReturn(
7576
if (endTimeStampNanos != null) {
76-
SentryNanotimeDate(Date(), endTimeStampNanos)
77+
SentryNanotimeDate(System.currentTimeMillis(), endTimeStampNanos)
7778
} else {
7879
null
7980
}
@@ -438,8 +439,8 @@ class SpanFrameMetricsCollectorTest {
438439
@Test
439440
fun `SentryNanoDate diff does nano precision`() {
440441
// having this in here, as SpanFrameMetricsCollector relies on this behavior
441-
val a = SentryNanotimeDate(Date(1234), 567)
442-
val b = SentryNanotimeDate(Date(1234), 0)
442+
val a = SentryNanotimeDate(1234, 567)
443+
val b = SentryNanotimeDate(1234, 0)
443444

444445
assertEquals(567, a.diff(b))
445446
}

0 commit comments

Comments
 (0)