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

feat: add timeZoneName props #744

Merged

Conversation

wood1986
Copy link
Collaborator

@wood1986 wood1986 commented Mar 25, 2023

Summary

This PR tries to fix the followings timezone related bugs

  1. timeZoneOffsetInMinutes does not support daylight saving.
  2. timezone offset on android is broken #528
  3. Issue with timezones on iOS #61

closes #547, closes #61, closes #528, closes #114

My solution to the timezone issues is to let OS interpret time zone by passing a timeZoneName props. JS side should not re-interpret or reconstruct JS Date object based on year, month, day, hour and minutes. Android is doing this and iOS is not. the JS should only need to care UTC timestamp like what iOS is doing.

All the timezone related operation should be handled on native side because OS has the full knowledge of all timezone and library.

The timeZoneName is based on IANA See https://www.iana.org/time-zones in both Android and iOS. But they are not completely identical. It has around 4XX in common. See https://gist.github.com/mteece/80fff3329074cf90d7991e55f4fc8de4 for NSTimeZone in Objective C and https://garygregory.wordpress.com/2013/06/18/what-are-the-java-timezone-ids/ for TimeZone in Java.

Test Plan

What's required for testing (prerequisites)?

What are the steps to reproduce (after prerequisites)?

Compatibility

OS Implemented
iOS
Android

Checklist

  • I have tested this on a device and a simulator
  • I added the documentation in README.md
  • I updated the typed files (TS and Flow)
  • I added a sample use of the API in the example project (example/App.js)
  • I have added automated tests, either in JS or e2e tests, as applicable

@wood1986
Copy link
Collaborator Author

I want to get a feedback from maintainer before writing the test

@wood1986 wood1986 force-pushed the feature/timezone-name branch 5 times, most recently from a0afd05 to 5a9d512 Compare March 27, 2023 07:29
@wood1986
Copy link
Collaborator Author

Hey @vonovak could you please take a look? Thanks

@vonovak
Copy link
Member

vonovak commented Apr 3, 2023

hello and thanks for the PR!

I'm a little swamped right now with other work that pays the bills and the PR is rather large so it will take me some time to get back to this.

Thank you for you patience! 🙂

@wood1986
Copy link
Collaborator Author

Any update?

@wood1986
Copy link
Collaborator Author

wood1986 commented May 8, 2023

Hey @vonovak, It has been a month. Any update? Thanks

Copy link
Member

@vonovak vonovak left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hello and thank you for your PR!
firstly, thank you for taking a stab at this long-term issue. It is one that I was planning on tackling but didn't manage to get to it due to being involved elsewhere. Also, thank you for your patience with getting back to you.

I do agree with the approach of removing JS from the equation and having the date logic live in the native land, so that's good!

I added a few comments that should result into making the code better.

When they are resolved, docs need to be updated as well. CI also needs to be green before merging.

To wrap up, this is a good direction AFAICT. Please address the review / reply to the comments if you disagree with them. Looking forward to merging! 🚀

src/index.js Outdated
@@ -3,7 +3,6 @@
* @flow strict-local
*/
import RNDateTimePicker from './datetimepicker';
export * from './eventCreators';
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this would be a change that is more breaking than needed, because the event creators are recommended to be used in tests that people may have, and they are also used in https://github.com/react-native-datetimepicker/datetimepicker/blob/master/test/userlandTestExamples.test.js

I believe it makes sense to keep them and just modify them as needed

src/types.js Outdated
* parameter, it is possible to force a certain timezone offset. For
* instance, to show times in Pacific Standard Time
*/
timeZoneName?: string,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please add this to BaseProps so that it's not duplicated twice?

src/index.d.ts Outdated
/**
* The tz database name in https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
*/
timeZoneName?: string;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please move to BaseProps, now it's only in IOSNativeProps

} from './androidUtils';
import pickers from './picker';
import {
createDateTimeSetEvtParams,
createDismissEvtParams,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please keep using these creators, as per the comment in index.js

+(NSSet *)knownTimeZoneNames {
static NSSet *knownTimeZoneNames = nil;
if (knownTimeZoneNames == nil) {
knownTimeZoneNames = [NSSet setWithArray:[NSTimeZone knownTimeZoneNames]];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please do without this? It's just copying an array into a set. For the check of whether a TZ is supported (in RNDateTimePickerManager.m), you can check the constructor return value: https://developer.apple.com/documentation/foundation/nstimezone/1387227-timezonewithname#return_value

c.set(Calendar.MILLISECOND, 999);
datePicker.setMaxDate(c.getTimeInMillis() - getOffset(c, timeZoneOffsetInMilliseconds));
}
datePicker.setMinDate(minDate);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please call these setters only when min / max date was set in JS?
I'm not sure what side effects there are when calling these setters and what bugs there are behind it - Android is quite unpredictable in this and I'd like to avoid potential issues, thanks

calendar.set(year, monthOfYear, dayOfMonth, 0, 0, 0);
long timestamp = Common.clamp(calendar.getTimeInMillis(), maxDate, minDate);
calendar.setTimeInMillis(timestamp);
datePicker.updateDate(calendar.get(Calendar.YEAR), calendar.get(Calendar.MONTH), calendar.get(Calendar.DAY_OF_MONTH));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you please double-check and comment that there is not a loop in updateDate -> OnDateChanged -> updateDate ... ? thanks

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good call

@@ -28,6 +35,7 @@ public class Common {
public static final String NEGATIVE = "negative";
public static final String LABEL = "label";
public static final String TEXT_COLOR = "textColor";
private static final HashSet TIMEZONE_IDS = new HashSet<>(Arrays.asList(TimeZone.getAvailableIDs()));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we please avoid this, and do the check in getTimeZone? I'm sure there's some way to avoid this copy, thx

import java.util.Calendar;

// fix for https://issuetracker.google.com/issues/169602180
// TODO revisit day, month, year with timezoneoffset fixes
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

less is more 👍

@wood1986
Copy link
Collaborator Author

I fixed the all comments and have not finished yet. Now I can fix the test as you give me a green light and I will do it tomorrow

@wood1986
Copy link
Collaborator Author

return;
}
}
RCTLogWarn(@"'%@' does not exist in NSTimeZone.knownTimeZoneNames fallback to localTimeZone=%@", json, NSTimeZone.localTimeZone.name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this warning will currently log even for cases when it shouldn't

if (timeZone != nil) {
picker.timeZone = timeZone;
} else {
RCTLogWarn(@"'%@' does not exist in NSTimeZone.knownTimeZoneNames fallback to localTimeZone=%@", timeZoneName, NSTimeZone.localTimeZone.name);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this will log even when it shouldn't

@vonovak
Copy link
Member

vonovak commented May 15, 2023

Hey @vonovak, I am unable to run e2e test both locally and remotely with the same error

see #758 - that should fix it

@vonovak
Copy link
Member

vonovak commented Jun 20, 2023

@wood1986 if you integrate the latest master, you should be able to run the example app and e2e tests. Let me know if you need any help, thanks! 👍

@wood1986
Copy link
Collaborator Author

wood1986 commented Jul 8, 2023

@vonovak, I am still unable to run the e2e test. It shows

image

@vonovak
Copy link
Member

vonovak commented Jul 8, 2023

There are two ways:

  1. remove the utilBinaryPaths entry in detoxrc

  2. run the tests on a "vanilla" emulator without Google services installed. You can create one from the command line the same way it's done in circle ci, see the circle ci config file, android/create-avd step.

You'll see the exact command if you look at some previous ci runs in circle ci. I'm away from keyboard so cannot give the exact command.

Thank you! 👍

@wood1986
Copy link
Collaborator Author

wood1986 commented Jul 9, 2023

Hey @vonovak, Now, I can run the test and I have fixed all the tests except tz related test cases. Thanks for that.

I want to completely remove all tzOffsetMinutes as I do not want to spend time on writing test for tzOffsetMinutes. What is your thought?

@vonovak
Copy link
Member

vonovak commented Jul 9, 2023

Please keep the code for tzOffsetMinutes the way it is (don't remove it, don't add tests). We'll remove the code in a later release.

What would be appreciated though is that if someone uses the tzOffsetMinutes prop, they get a depreciation warning, asking them to use the new prop instead. Thank you! 👍

@wood1986
Copy link
Collaborator Author

Now, I cannot run e2e test for iOS. It crashes on launch but I can launch it without detox

@vonovak
Copy link
Member

vonovak commented Jul 10, 2023

@wood1986 in CI, the ios tests appear to run just fine, so if they are crashing for you, it seems it's something that is present with you locally.
Is your branch up to date with master branch? It shouldn't really matter but I recently updated detox to latest stable... Not sure really.

Also, not sure why, as the tests are passing on Android, but I see failures with label not matching expectation (ax.id = "utcTime"; text = "2000-01-01T14:44:00Z", expected: toHaveText('2021-11-13T14:44:00Z') and trying to scroll com.facebook.react.views.scroll.ReactHorizontalScrollView (such component won't exists on ios).

In case you end up running out of time / patience, let me know and I can take it over the finish line, most of the work is done afaict. Thank you! 👍

@wood1986
Copy link
Collaborator Author

wood1986 commented Jul 10, 2023

Thanks @vonovak

I have not updated the test for iOS yet. android is completed except one test case in new architecture.

My branch is up to date and it has all the latest change from master. Please run it on your side and let me know how I can run it locally. I want to update all the tests. I was using iOS 16 and iPhone 14 simulator

@wood1986 wood1986 force-pushed the feature/timezone-name branch 3 times, most recently from 1c96f27 to 1e019c6 Compare July 11, 2023 05:08
@wood1986 wood1986 force-pushed the feature/timezone-name branch 2 times, most recently from af8a5b5 to d0a0bb0 Compare July 11, 2023 17:29
@wood1986
Copy link
Collaborator Author

Hey @vonovak, Finally, I have just updated all the the tests. The test is a bit unstable. Only you can rerun the test. Please re-review everything as I did a force push.

By the way, I am still unable to run the test on iOS and I was using the build machine result to fix the tests

@wood1986 wood1986 requested a review from vonovak July 12, 2023 12:19
@vonovak
Copy link
Member

vonovak commented Aug 2, 2023

hello @wood1986 thank you for your work, and sorry to keep you waiting, I'm going to take a look at this next week! 👍

@vonovak vonovak merged commit d136216 into react-native-datetimepicker:master Aug 29, 2023
4 checks passed
@vonovak
Copy link
Member

vonovak commented Aug 29, 2023

@wood1986 thank you for your patience and your PR, it'll be released soon! 🙂 💯

vonovak pushed a commit that referenced this pull request Aug 29, 2023
# [7.5.0](v7.4.2...v7.5.0) (2023-08-29)

### Features

* add timeZoneName prop ([#744](#744)) ([d136216](d136216))
@vonovak
Copy link
Member

vonovak commented Aug 29, 2023

🎉 This issue has been resolved in version 7.5.0 🎉

If this package helps you, consider sponsoring us! 🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
2 participants