Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TZDateTimes at same instant and location from different isolates are not equal #185

Open
jamesncl opened this issue Dec 15, 2023 · 0 comments

Comments

@jamesncl
Copy link

Comparing two identical TZDateTimes created in different isolates fails, because Location uses identity not equality for ==. For example:

  final rootIsolateToken = RootIsolateToken.instance!;
    
  TZDateTime fromRootIsolateA = TZDateTime(getLocation('America/Detroit'), 2023);
  TZDateTime fromRootIsolateB = TZDateTime(getLocation('America/Detroit'), 2023);
  TZDateTime fromComputeIsolate = await Isolate.run<TZDateTime>(() {
    BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
    initializeTimeZones();
    return TZDateTime(getLocation('America/Detroit'), 2023);
  });

  print("fromRootIsolateA == fromRootIsolateB ${fromRootIsolateA == fromRootIsolateB}");
  print("fromRootIsolateA == fromComputeIsolate ${fromRootIsolateA == fromComputeIsolate}");

Actual results:

I/flutter (24040): fromRootIsolateA == fromRootIsolateB true
I/flutter (24040): fromRootIsolateA == fromComputeIsolate false

I would expect both tests to return true, as per the documentation for the == operator on TZDateTime:

/// Returns true if [other] is a [TZDateTime] at the same moment and in the
  /// same [Location].
  /// ...
  @override
  bool operator ==(Object other) {
    return identical(this, other) ||
        other is TZDateTime &&
            _native.isAtSameMomentAs(other._native) &&
            location == other.location;
  }

I think this is failing when the TZDateTime is created in a different isolate because Location does not override == so falls back on an identity check, which fails because it comes from a different instance of the location which was created inside the second isolate.

I suggest that Location should implement == and return true if the location names are the same?

Minimal reproducible example
import 'dart:isolate';

import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:timezone/data/latest.dart';
import 'package:timezone/timezone.dart';

void main() {
  initializeTimeZones();
  runApp(const MaterialApp(
    home: Example(),
  ));
}


class Example extends StatefulWidget {

  const Example();

  @override
  State<Example> createState() => _ExampleState();
}

class _ExampleState extends State<Example> {

  @override
  void initState() {
    _test();
    super.initState();
  }

  Future<void> _test() async {

    final rootIsolateToken = RootIsolateToken.instance!;

    TZDateTime fromRootIsolateA = TZDateTime(getLocation('America/Detroit'), 2023);
    TZDateTime fromRootIsolateB = TZDateTime(getLocation('America/Detroit'), 2023);
    TZDateTime fromComputeIsolate = await Isolate.run<TZDateTime>(() {
      BackgroundIsolateBinaryMessenger.ensureInitialized(rootIsolateToken);
      initializeTimeZones();
      return TZDateTime(getLocation('America/Detroit'), 2023);
    });

    print("fromRootIsolateA == fromRootIsolateB ${fromRootIsolateA == fromRootIsolateB}");
    print("fromRootIsolateA == fromComputeIsolate ${fromRootIsolateA == fromComputeIsolate}");
  }

  @override
  Widget build(BuildContext context) {
    return Container();
  }
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant