Skip to content

Commit

Permalink
added timezone
Browse files Browse the repository at this point in the history
  • Loading branch information
pranshugupta54 committed Oct 10, 2024
1 parent 6be82c3 commit fcc0c38
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 6 deletions.
12 changes: 12 additions & 0 deletions lib/services/database_mutation_functions.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import 'package:talawa/locator.dart';
import 'package:talawa/models/organization/org_info.dart';
import 'package:talawa/utils/post_queries.dart';
import 'package:talawa/utils/queries.dart';
import 'package:talawa/view_model/connectivity_view_model.dart';
import 'package:talawa/utils/time_conversion.dart';

/// DataBaseMutationFunctions class provides different services that are under the context of graphQL mutations and queries.
///
Expand Down Expand Up @@ -97,6 +99,8 @@ class DataBaseMutationFunctions {
return await gqlAuthQuery(query, variables: variables);
}
} else if (result.data != null && result.isConcrete) {
traverseAndConvertDates(result.data as Map<String, dynamic>,
convertUTCToLocal, splitDateTimeLocal);
return result;
}
return noData;
Expand All @@ -117,6 +121,9 @@ class DataBaseMutationFunctions {
String mutation, {
Map<String, dynamic>? variables,
}) async {
if (variables != null) {
traverseAndConvertDates(variables, convertLocalToUTC, splitDateTimeUTC);
}
final MutationOptions options = MutationOptions(
document: gql(mutation),
variables: variables ?? <String, dynamic>{},
Expand Down Expand Up @@ -157,6 +164,9 @@ class DataBaseMutationFunctions {
Map<String, dynamic>? variables,
bool reCall = true,
}) async {
if (variables != null) {
traverseAndConvertDates(variables, convertLocalToUTC, splitDateTimeUTC);
}
final MutationOptions options = MutationOptions(
document: gql(mutation),
variables: variables ?? <String, dynamic>{},
Expand Down Expand Up @@ -209,6 +219,8 @@ class DataBaseMutationFunctions {
result.exception!,
);
} else if (result.data != null && result.isConcrete) {
traverseAndConvertDates(result.data as Map<String, dynamic>,
convertUTCToLocal, splitDateTimeLocal);
return result;
}
return noData;
Expand Down
8 changes: 4 additions & 4 deletions lib/services/event_service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -59,17 +59,17 @@ class EventService extends BaseFeedManager<Event> {
final String currentOrgID = _currentOrg.id!;
// mutation to fetch the events
final String mutation = EventQueries().fetchOrgEvents(currentOrgID);
final result = await _dbFunctions.gqlAuthMutation(mutation);
final result = await _dbFunctions.gqlAuthQuery(mutation);

if (result.data == null) {
throw Exception('unable to fetch data');
}

print(result.data!["eventsByOrganizationConnection"]);
final List<Map<String, dynamic>> eventsJson = result
.data!["eventsByOrganizationConnection"] as List<Map<String, dynamic>>;
final eventsJson = result
.data!["eventsByOrganizationConnection"] as List<dynamic>;
eventsJson.forEach((eventJsonData) {
final Event event = Event.fromJson(eventJsonData);
final Event event = Event.fromJson(eventJsonData as Map<String,dynamic>);
event.isRegistered = event.attendees?.any(
(attendee) => attendee.id == _userConfig.currentUser.id,
) ??
Expand Down
93 changes: 93 additions & 0 deletions lib/utils/time_conversion.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
import 'package:intl/intl.dart';

String combineDateTime(String date, String time) {
return '$date $time';
}

Map<String, String> splitDateTimeUTC(String dateTimeStr) {
final DateTime dateTime = DateTime.parse(dateTimeStr);
return {
'date': DateFormat('yyyy-MM-dd').format(dateTime),
'time': DateFormat('HH:mm:ss.SSS\'Z\'').format(dateTime),
};
}
Map<String, String> splitDateTimeLocal(String dateTimeStr) {
final DateTime dateTime = DateTime.parse(dateTimeStr);
return {
'date': DateFormat('yyyy-MM-dd').format(dateTime),
'time': DateFormat('HH:mm').format(dateTime),
};
}

String convertUTCToLocal(String utcTime) {
final DateTime dateTime = DateTime.parse(utcTime).toLocal();
return DateFormat('yyyy-MM-ddTHH:mm:ss.SSS').format(dateTime);
}

String convertLocalToUTC(String localTime) {
final DateTime dateTime = DateTime.parse(localTime).toUtc();
return DateFormat('yyyy-MM-ddTHH:mm:ss.SSS\'Z\'').format(dateTime);
}

void traverseAndConvertDates(
Map<String, dynamic> obj,
String Function(String) convertFn,
Map<String, String> Function(String) splitFn,
) {
obj.forEach((key, value) {

final pairedFields =
dateTimeFields['pairedFields']?.cast<Map<String, String>>();
if (pairedFields != null) {
for (var field in pairedFields) {
if (key == field['dateField'] && obj.containsKey(field['timeField'])) {
final combinedDateTime = combineDateTime(
obj[field['dateField']] as String,
obj[field['timeField']] as String,
);

final convertedDateTime = convertFn(combinedDateTime);

final splitDateTime = splitFn(convertedDateTime ?? '');

obj[field['dateField'] as String] = splitDateTime['date'] ?? '';
obj[field['timeField'] as String] = splitDateTime['time'] ?? '';
}
}
}

if (dateTimeFields['directFields']?.cast<String>()?.contains(key) ??
false) {
obj[key] = convertFn(value as String);
}

if (value is Map<String, dynamic>) {
traverseAndConvertDates(value, convertFn, splitFn);
} else if (value is List) {
for (var item in value) {
if (item is Map<String, dynamic>) {
traverseAndConvertDates(item, convertFn, splitFn);
}
}
}
});
}

const dateTimeFields = {
'directFields': [
'createdAt',
'birthDate',
'updatedAt',
'recurrenceStartDate',
'recurrenceEndDate',
'pluginCreatedBy',
'dueDate',
'completionDate',
'startCursor',
'endCursor',
],
'pairedFields': [
{'dateField': 'startDate', 'timeField': 'startTime'},
{'dateField': 'endDate', 'timeField': 'endTime'},
],
};
Original file line number Diff line number Diff line change
Expand Up @@ -227,10 +227,10 @@ class CreateEventViewModel extends BaseModel {
'endDate': DateFormat('yyyy-MM-dd').format(eventEndDate),
'startTime': isAllDay
? null
: '${DateFormat('HH:mm:ss').format(startTime)}Z',
: '${DateFormat('HH:mm:ss').format(startTime)}',
'endTime': isAllDay
? null
: '${DateFormat('HH:mm:ss').format(endTime)}Z',
: '${DateFormat('HH:mm:ss').format(endTime)}',
},
if (isRecurring)
'recurrenceRuleData': {
Expand Down
108 changes: 108 additions & 0 deletions test/widget_tests/after_auth_screens/events/time_conversion_test.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';
import 'package:talawa/utils/time_conversion.dart';
import '../../../helpers/test_helpers.dart';
import 'package:clock/clock.dart';

void main() {
group('Time Conversion Utils', () {
setUp(() {
registerServices();
});

tearDown(() {
unregisterServices();
});

test('combineDateTime combines date and time correctly', () {
expect(combineDateTime('2023-05-01', '14:30:00'), '2023-05-01 14:30:00');
});

test('splitDateTimeUTC splits UTC datetime correctly', () {
final result = splitDateTimeUTC('2023-05-01T14:30:00.000Z');
expect(result['date'], '2023-05-01');
expect(result['time'], '14:30:00.000Z');
});

test('splitDateTimeLocal splits local datetime correctly', () {
final result = splitDateTimeLocal('2023-05-01T14:30:00.000');
expect(result['date'], '2023-05-01');
expect(result['time'], '14:30');
});

test('convertUTCToLocal converts UTC to local time', () {
final utcTime = '2023-05-01T14:30:00.000Z';
final localTime = convertUTCToLocal(utcTime);
expect(localTime, isNot(equals(utcTime)));
expect(
localTime, matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$'));
});

test('convertLocalToUTC converts local to UTC time', () {
final localTime = '2023-05-01T14:30:00.000';
final utcTime = convertLocalToUTC(localTime);
expect(utcTime, isNot(equals(localTime)));
expect(
utcTime, matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}Z$'));
});

group('traverseAndConvertDates', () {
test('converts direct fields', () {
final testObj = {
'createdAt': '2023-05-01T14:30:00.000Z',
'name': 'Test',
};
traverseAndConvertDates(testObj, convertUTCToLocal, splitDateTimeLocal);
expect(testObj['createdAt'], isNot(equals('2023-05-01T14:30:00.000Z')));
expect(testObj['createdAt'],
matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$'));
});

test('converts paired fields', () {
final testObj = {
'startDate': '2023-05-01',
'startTime': '14:30:00',
'name': 'Test',
};
traverseAndConvertDates(testObj, convertUTCToLocal, splitDateTimeLocal);
expect(testObj['startDate'], '2023-05-01');
expect(testObj['startTime'], matches(r'^\d{2}:\d{2}$'));
});

test('converts nested objects', () {
final testObj = {
'user': {
'createdAt': '2023-05-01T14:30:00.000Z',
'name': 'Test User',
},
};
traverseAndConvertDates(testObj, convertUTCToLocal, splitDateTimeLocal);
expect(testObj['user']?['createdAt'],
isNot(equals('2023-05-01T14:30:00.000Z')));
expect(testObj['user']?['createdAt'],
matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$'));
});

test('converts objects in lists', () {
withClock(Clock.fixed(DateTime.utc(2023, 5, 1, 12, 0)), () {
final testObj = {
'items': [
{'createdAt': '2023-05-01T14:30:00.000Z'},
{'createdAt': '2023-05-02T15:45:00.000Z'},
],
};
traverseAndConvertDates(
testObj, convertUTCToLocal, splitDateTimeLocal);
expect(testObj['items']?[0]['createdAt'],
isNot(equals('2023-05-01T14:30:00.000Z')));
expect(testObj['items']?[0]['createdAt'],
matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$'));
expect(testObj['items']?[1]['createdAt'],
isNot(equals('2023-05-02T15:45:00.000Z')));
expect(testObj['items']?[1]['createdAt'],
matches(r'^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}$'));
});
});
});
});
}

0 comments on commit fcc0c38

Please sign in to comment.