react-native-timezone 3.1.0 β†’ 3.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,28 +1,91 @@
1
1
  # React Native Timezone and Region
2
2
 
3
- [![Maintainability](https://api.codeclimate.com/v1/badges/3713253a365fe6a55615/maintainability)](https://codeclimate.com/github/samitha9125/react-native-timezone/maintainability)
4
-
5
3
  A Simple react native module to get the Timezone and the Region of the Android/iOS devices.
6
4
 
7
- # Motivation
5
+ # Why Choose This Library?
6
+
7
+ ## πŸ”’ Privacy-First
8
+ Unlike other timezone/region libraries, `react-native-timezone` **does NOT require**:
9
+ - ❌ Location permissions (`ACCESS_FINE_LOCATION`, `ACCESS_COARSE_LOCATION`)
10
+ - ❌ `READ_PHONE_STATE` permission (Android)
11
+ - ❌ Additional native dependencies
12
+
13
+ **This is critical for:**
14
+ - Privacy-conscious apps
15
+ - App Store/Play Store approval (permission justifications)
16
+ - GDPR/CCPA compliance
17
+
18
+ ## πŸ“± Expo Compatible
19
+ Works seamlessly with **Expo Development Builds** (CNG - Continuous Native Generation):
20
+ ```bash
21
+ npx expo install react-native-timezone
22
+ npx expo prebuild
23
+ npx expo run:ios
24
+ ```
8
25
 
9
- For a project of mine, I had to acquire the currently selected timezone of the user. Unfortunately, I could not find any react native package or react native in-build function that facilitates this. Thus I created a small library.
26
+ No need for bare React Native workflowβ€”just prebuild and run.
10
27
 
11
- v3.0.0 and above, you can access the Region details. More details can be found below.
28
+ ## ⚑ Super Lightweight
29
+ - Zero JavaScript dependencies
30
+ - Native TurboModule (synchronous, no bridge overhead)
31
+ - Minimal footprint (~2KB gzipped)
32
+
33
+ ## πŸ†• Modern Architecture
34
+ Fully compatible with React Native's New Architecture (Fabric + TurboModules).
35
+
36
+ ---
12
37
 
13
38
  # Compatibility
14
39
 
15
- Timezone version 3.0.0 only supports React Native version 0.62.3 and above due to the React Native Regular Expression Denial of Service (ReDoS) vulnerability.
40
+ | React Native | New Architecture | Tested | Notes |
41
+ |--------------|------------------|--------|-------|
42
+ | 0.71.x | βœ… Stable | βœ… | First stable TurboModule support |
43
+ | 0.72.x | βœ… | βœ… | |
44
+ | 0.73.x | βœ… | βœ… | |
45
+ | 0.74.x | βœ… Default | βœ… | New Arch enabled by default |
46
+ | 0.76.x | βœ… | βœ… | |
47
+ | 0.83.x | βœ… | βœ… | Latest (Feb 2026) |
48
+
49
+ **Breaking Changes in React Native:**
50
+ - **0.71**: New Architecture stabilized (TurboModules + Fabric)
51
+ - **0.74**: New Architecture enabled by default
52
+ - **0.76**: Minimum iOS deployment target raised to iOS 15.1
53
+
54
+ ---
55
+
56
+ # ⚠️ Important: iOS Carrier API Deprecation
57
+
58
+ Apple has deprecated the entire `CTCarrier` class with **no replacement API**:
59
+
60
+ | API | Deprecated Since | Status |
61
+ |-----|-----------------|--------|
62
+ | `subscriberCellularProvider` | iOS 12 | ⚠️ Deprecated |
63
+ | `serviceSubscriberCellularProviders` | iOS 16 | ⚠️ Deprecated |
64
+ | `CTCarrier` class | iOS 16 | ❌ No replacement |
16
65
 
17
- | React native version | Tested | Result |
18
- | -------------------- | ------ | ------ |
19
- | 0.70.0 + | βœ… | βœ… |
20
- | 0.73.0 + | βœ… | βœ… |
21
- | 0.76.5 + | βœ… | βœ… |
66
+ **What this means for `getRegionByTelephony()`:**
67
+ - **iOS < 18**: Works, but triggers deprecation warnings (suppressed in this library)
68
+ - **iOS 18+**: Returns `null` due to Apple's privacy restrictions
69
+
70
+ **Recommended Pattern:**
71
+ ```javascript
72
+ // Use telephony-based region with locale fallback
73
+ const region = Timezone.getRegionByTelephony() ?? Timezone.getRegionByLocale();
74
+ ```
75
+
76
+ This is an Apple platform limitation, not a bug in this library.
77
+
78
+ ---
79
+
80
+ # Motivation
81
+
82
+ For a project of mine, I had to acquire the currently selected timezone of the user. Unfortunately, I could not find any react native package or react native in-build function that facilitates this. Thus I created a small library.
83
+
84
+ v3.0.0 and above, you can access the Region details. More details can be found below.
22
85
 
23
86
  # Installation
24
87
 
25
- `npm i react-native-timezone`
88
+ `yarn add react-native-timezone`
26
89
 
27
90
  ## iOS
28
91
 
@@ -54,5 +117,5 @@ Check out the [example](https://github.com/samitha9125/react-native-timezone/tre
54
117
  | --------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
55
118
  | getTimeZone | Android: Returns timezone ID using `java.util.TimeZone.getID()`<br>iOS: Reflects the current system time zone using `localTimeZone` of `NSTimeZone` |
56
119
  | isAutoTimeZoneEnabled | Returns a boolean indicating if auto timezone is enabled on the device **(Android Only)** |
57
- | getRegionByTelephony | Retrieves the region information based on the telephony (SIM card) of the device. Returns `undefined` if the device has no SIM card. |
120
+ | getRegionByTelephony | Retrieves the region information based on the telephony (SIM card) of the device. Returns `null` if the device has no SIM card. |
58
121
  | getRegionByLocale | Retrieves the region information based on the device's locale settings |
@@ -1,6 +1,7 @@
1
1
  package com.samitha.timezone
2
2
 
3
3
  import android.content.ContentResolver
4
+ import android.content.Context
4
5
  import android.os.Build
5
6
  import android.provider.Settings
6
7
  import android.telephony.TelephonyManager
@@ -54,7 +55,7 @@ class TimezoneModule(reactContext: ReactApplicationContext) :
54
55
  @ReactMethod(isBlockingSynchronousMethod = true)
55
56
  override fun getRegionByTelephony(): String? {
56
57
  return try {
57
- val telephonyService = reactApplicationContext.getSystemService(ReactApplicationContext.TELEPHONY_SERVICE) as? TelephonyManager
58
+ val telephonyService = reactApplicationContext.getSystemService(Context.TELEPHONY_SERVICE) as? TelephonyManager
58
59
  telephonyService?.networkCountryIso
59
60
  } catch (e: Exception) {
60
61
  null
package/ios/Timezone.mm CHANGED
@@ -3,7 +3,7 @@
3
3
  #import "Timezone.h"
4
4
 
5
5
  @implementation Timezone
6
- RCT_EXPORT_MODULE('Timezone');
6
+ RCT_EXPORT_MODULE(Timezone);
7
7
  /**
8
8
  * This is a Synchronous method.
9
9
  * Retrieves the current time zone name.
@@ -17,15 +17,48 @@
17
17
  /**
18
18
  * Synchronous method.
19
19
  * Gets the region based on the telephony manager's network country ISO.
20
+ *
21
+ * ⚠️ DEPRECATION NOTICE:
22
+ * - subscriberCellularProvider: Deprecated iOS 12+
23
+ * - serviceSubscriberCellularProviders: Deprecated iOS 16+
24
+ * - CTCarrier class: Deprecated iOS 16+ with NO REPLACEMENT
25
+ *
26
+ * Starting iOS 18, these APIs return nil due to privacy restrictions.
27
+ * Apple has intentionally removed carrier info access with no alternative.
28
+ * Consider using getRegionByLocale() as a fallback.
20
29
  */
21
30
  RCT_EXPORT_BLOCKING_SYNCHRONOUS_METHOD(getRegionByTelephony)
22
31
  {
32
+ #pragma clang diagnostic push
33
+ #pragma clang diagnostic ignored "-Wdeprecated-declarations"
34
+
23
35
  CTTelephonyNetworkInfo *networkInfo = [[CTTelephonyNetworkInfo alloc] init];
24
- CTCarrier *carrier = [networkInfo subscriberCellularProvider];
25
- NSString *isoCountryCode = [carrier isoCountryCode];
36
+ NSString *isoCountryCode = nil;
37
+
38
+ // iOS 12+: Check all cellular providers (multi-SIM support)
39
+ if (@available(iOS 12.0, *)) {
40
+ NSDictionary *carriers = [networkInfo serviceSubscriberCellularProviders];
41
+
42
+ if (carriers && carriers.count > 0) {
43
+ // Get the first available carrier's country code
44
+ CTCarrier *carrier = [carriers.allValues firstObject];
45
+ isoCountryCode = [carrier isoCountryCode];
46
+ }
47
+ }
48
+
49
+ // Fallback for iOS < 12 OR if iOS 12+ returns nothing
50
+ if (isoCountryCode == nil || [isoCountryCode isEqualToString:@""]) {
51
+ CTCarrier *carrier = [networkInfo subscriberCellularProvider];
52
+ isoCountryCode = [carrier isoCountryCode];
53
+ }
54
+
55
+ #pragma clang diagnostic pop
56
+
57
+ // iOS 18+: Will likely return nil due to privacy restrictions
26
58
  if (isoCountryCode == nil || [isoCountryCode isEqualToString:@""]) {
27
59
  return nil;
28
60
  }
61
+
29
62
  return isoCountryCode;
30
63
  }
31
64
 
package/package.json CHANGED
@@ -1,10 +1,19 @@
1
1
  {
2
2
  "name": "react-native-timezone",
3
- "version": "3.1.0",
3
+ "version": "3.2.0",
4
4
  "description": "A Simple react native module to get Timezone and Region of the Android/iOS devices.",
5
5
  "source": "./src/index.tsx",
6
6
  "main": "./lib/commonjs/index.js",
7
7
  "module": "./lib/module/index.js",
8
+ "scripts": {
9
+ "example": "pnpm --filter react-native-timezone-example",
10
+ "test": "jest",
11
+ "typecheck": "tsc",
12
+ "lint": "eslint \"**/*.{js,ts,tsx}\"",
13
+ "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
14
+ "prepare": "bob build",
15
+ "release": "release-it"
16
+ },
8
17
  "exports": {
9
18
  ".": {
10
19
  "import": {
@@ -22,7 +31,6 @@
22
31
  "lib",
23
32
  "android",
24
33
  "ios",
25
- "cpp",
26
34
  "*.podspec",
27
35
  "react-native.config.js",
28
36
  "!ios/build",
@@ -36,20 +44,6 @@
36
44
  "!**/__mocks__",
37
45
  "!**/.*"
38
46
  ],
39
- "scripts": {
40
- "example": "yarn workspace react-native-timezone-example",
41
- "test": "jest",
42
- "typecheck": "tsc",
43
- "lint": "eslint \"**/*.{js,ts,tsx}\"",
44
- "clean": "del-cli android/build example/android/build example/android/app/build example/ios/build lib",
45
- "prepare": "bob build",
46
- "release": "release-it"
47
- },
48
- "keywords": [
49
- "react-native",
50
- "ios",
51
- "android"
52
- ],
53
47
  "repository": {
54
48
  "type": "git",
55
49
  "url": "git+https://github.com/samitha9125/react-native-timezone.git"
@@ -89,69 +83,10 @@
89
83
  "@types/react": "^18.2.44"
90
84
  },
91
85
  "peerDependencies": {
92
- "react": "*",
93
- "react-native": "*"
94
- },
95
- "workspaces": [
96
- "example"
97
- ],
98
- "packageManager": "yarn@3.6.1",
99
- "jest": {
100
- "preset": "react-native",
101
- "modulePathIgnorePatterns": [
102
- "<rootDir>/example/node_modules",
103
- "<rootDir>/lib/"
104
- ]
105
- },
106
- "commitlint": {
107
- "extends": [
108
- "@commitlint/config-conventional"
109
- ]
110
- },
111
- "release-it": {
112
- "git": {
113
- "commitMessage": "chore: release ${version}",
114
- "tagName": "v${version}",
115
- "requireBranch": "main"
116
- },
117
- "npm": {
118
- "publish": true
119
- },
120
- "github": {
121
- "release": true
122
- }
123
- },
124
- "eslintConfig": {
125
- "root": true,
126
- "extends": [
127
- "@react-native",
128
- "prettier"
129
- ],
130
- "rules": {
131
- "react/react-in-jsx-scope": "off",
132
- "prettier/prettier": [
133
- "error",
134
- {
135
- "quoteProps": "consistent",
136
- "singleQuote": true,
137
- "tabWidth": 2,
138
- "trailingComma": "es5",
139
- "useTabs": false
140
- }
141
- ]
142
- }
143
- },
144
- "eslintIgnore": [
145
- "node_modules/",
146
- "lib/"
147
- ],
148
- "prettier": {
149
- "quoteProps": "consistent",
150
- "singleQuote": true,
151
- "tabWidth": 2,
152
- "trailingComma": "es5",
153
- "useTabs": false
86
+ "react": ">=18.0.0",
87
+ "react-native": ">=0.71.0"
154
88
  },
89
+ "packageManager": "pnpm@9.15.4",
155
90
  "react-native-builder-bob": {
156
91
  "source": "src",
157
92
  "output": "lib",