Last active
November 26, 2025 06:19
-
-
Save Vonarian/d769bb38afc5d1368cfe6e8b6eaba27e to your computer and use it in GitHub Desktop.
Time calculation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import 'dart:core'; | |
| // Define the start and end times for the main work period | |
| // These can now be "h:mm AM/PM" or "HH:mm" | |
| // Example for 24-hour format: | |
| // String startTimeStr = "08:46"; | |
| // String endTimeStr = "17:30"; | |
| // Example for mixed formats: | |
| // String startTimeStr = "8:46 AM"; | |
| // String endTimeStr = "17:30"; | |
| String startTimeStr = "08:24 AM"; | |
| String endTimeStr = "5:33 PM"; | |
| // Define a list of leave periods | |
| final List<LeaveTime> leavePeriods = [ | |
| LeaveTime(start: "12:00 PM", end: "1:00 PM"), // Lunch | |
| LeaveTime(start: "3:00 PM", end: "3:15 PM"), // Short break | |
| // Example of an unparsable leave time to test error handling | |
| // LeaveTime(start: "invalid", end: "1:00 PM"), | |
| // Example of an invalid leave period (end before start) | |
| // LeaveTime(start: "3:00 PM", end: "2:00 PM"), | |
| ]; | |
| /// Parses a time string, supporting both "h:mm AM/PM" (12-hour) | |
| /// and "HH:mm" (24-hour) formats. | |
| /// | |
| /// Returns a [DateTime] object with a fixed arbitrary date (Jan 1, 2025) | |
| /// and the parsed time, or `null` if the string cannot be parsed. | |
| DateTime? parseTime(String timeStr) { | |
| try { | |
| final timeStrUpper = timeStr.toUpperCase(); | |
| final is12HourFormat = | |
| timeStrUpper.contains("AM") || timeStrUpper.contains("PM"); | |
| int hour; | |
| int minute; | |
| if (is12HourFormat) { | |
| final parts = timeStr.split(" "); | |
| if (parts.length != 2) return null; // Expected "time meridian" | |
| final hmParts = parts[0].split(":"); | |
| if (hmParts.length != 2) return null; // Expected "h:mm" | |
| hour = int.parse(hmParts[0]); | |
| minute = int.parse(hmParts[1]); | |
| String meridian = parts[1].toUpperCase(); | |
| if (meridian == "PM" && hour != 12) { | |
| hour += 12; | |
| } else if (meridian == "AM" && hour == 12) { | |
| hour = 0; // 12 AM (midnight) is 00:xx in 24-hour format | |
| } | |
| // Basic validation for parsed hour/minute values | |
| if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { | |
| return null; | |
| } | |
| } else { | |
| // Assume 24-hour format (HH:mm) | |
| final hmParts = timeStr.split(":"); | |
| if (hmParts.length != 2) return null; // Expected "HH:mm" | |
| hour = int.parse(hmParts[0]); | |
| minute = int.parse(hmParts[1]); | |
| // Basic validation for parsed hour/minute values | |
| if (hour < 0 || hour > 23 || minute < 0 || minute > 59) { | |
| return null; | |
| } | |
| } | |
| // Use a fixed date; only the time component is relevant for duration. | |
| return DateTime(2025, 1, 1, hour, minute); | |
| } on FormatException { | |
| // Catch errors from int.parse if the number format is invalid | |
| return null; | |
| } catch (e) { | |
| // Catch any other unexpected errors during parsing | |
| return null; | |
| } | |
| } | |
| /// Represents a period of leave time with a start and end time string. | |
| class LeaveTime { | |
| final String start; | |
| final String end; | |
| LeaveTime({required this.start, required this.end}); | |
| /// Calculates the duration of this leave period. | |
| /// Returns a [Duration] object, or `null` if parsing fails for start or end time, | |
| /// or if the end time is before the start time. | |
| Duration? getDuration() { | |
| final DateTime? startTime = parseTime(start); | |
| final DateTime? endTime = parseTime(end); | |
| if (startTime == null) { | |
| print( | |
| "Warning: Could not parse leave start time '$start'. Skipping this leave period.", | |
| ); | |
| return null; | |
| } | |
| if (endTime == null) { | |
| print( | |
| "Warning: Could not parse leave end time '$end'. Skipping this leave period.", | |
| ); | |
| return null; | |
| } | |
| // A leave duration should always be positive. If end is before start, it's invalid. | |
| if (endTime.isBefore(startTime)) { | |
| print( | |
| "Warning: Leave end time '$end' is before start time '$start'. Skipping this leave period.", | |
| ); | |
| return null; | |
| } | |
| return endTime.difference(startTime); | |
| } | |
| } | |
| void main() { | |
| DateTime? startTime = parseTime(startTimeStr); | |
| DateTime? endTime = parseTime(endTimeStr); | |
| if (startTime == null) { | |
| print( | |
| "Error: Could not parse main work start time '$startTimeStr'. Please use 'h:mm AM/PM' or 'HH:mm' format.", | |
| ); | |
| return; | |
| } | |
| if (endTime == null) { | |
| print( | |
| "Error: Could not parse main work end time '$endTimeStr'. Please use 'h:mm AM/PM' or 'HH:mm' format.", | |
| ); | |
| return; | |
| } | |
| // Calculate total scheduled work duration | |
| Duration scheduledWorkDuration = endTime.difference(startTime); | |
| // If the end time is before the start time for the main work, it's an error in this context. | |
| if (scheduledWorkDuration.isNegative) { | |
| print( | |
| "Error: Main work end time '$endTimeStr' is before start time '$startTimeStr'. " | |
| "Please ensure end time is after start time on the same day.", | |
| ); | |
| return; | |
| } | |
| // Calculate total leave duration from the list of leave periods | |
| Duration totalLeaveDuration = Duration.zero; | |
| for (final leave in leavePeriods) { | |
| final Duration? leaveDuration = leave.getDuration(); | |
| if (leaveDuration != null) { | |
| totalLeaveDuration += leaveDuration; | |
| } | |
| } | |
| // Calculate net work duration by subtracting total leave from scheduled work | |
| Duration netWorkDuration = scheduledWorkDuration - totalLeaveDuration; | |
| // Ensure net work duration is not negative (e.g., if leave times exceed scheduled work time) | |
| if (netWorkDuration.isNegative) { | |
| netWorkDuration = Duration.zero; | |
| } | |
| // --- Display scheduled work details --- | |
| final int totalMinutesScheduled = scheduledWorkDuration.inMinutes; | |
| final int totalHoursScheduled = | |
| totalMinutesScheduled ~/ 60; // Integer division | |
| final int minuteAfterHoursScheduled = totalMinutesScheduled % 60; // Remainder | |
| print( | |
| "Scheduled work time from $startTimeStr to $endTimeStr is " | |
| "$totalMinutesScheduled minutes / ${totalHoursScheduled}h ${minuteAfterHoursScheduled}m.", | |
| ); | |
| // --- Display leave details (if any) --- | |
| if (totalLeaveDuration.inMinutes > 0) { | |
| final int totalMinutesLeave = totalLeaveDuration.inMinutes; | |
| final int totalHoursLeave = totalMinutesLeave ~/ 60; | |
| final int minuteAfterHoursLeave = totalMinutesLeave % 60; | |
| print( | |
| "Total leave time applied: $totalMinutesLeave minutes / ${totalHoursLeave}h ${minuteAfterHoursLeave}m.", | |
| ); | |
| } else { | |
| print("No leave periods were applied."); | |
| } | |
| // --- Display net work details --- | |
| final int netTotalMinutes = netWorkDuration.inMinutes; | |
| final int netTotalHours = netTotalMinutes ~/ 60; | |
| final int netMinuteAfterHours = netTotalMinutes % 60; | |
| print( | |
| "Net work time after leave is $netTotalMinutes minutes / ${netTotalHours}h ${netMinuteAfterHours}m.", | |
| ); | |
| // --- Check against minimum work requirement --- | |
| const int requiredWorkMinutes = 480; // 8 hours * 60 minutes/hour | |
| if (netTotalMinutes < requiredWorkMinutes) { | |
| print( | |
| '\n!!!!!!Net work time (${netTotalMinutes}m) does not meet the minimum work requirement of ${requiredWorkMinutes} minutes!!!!!!', | |
| ); | |
| print('You are short by ${requiredWorkMinutes - netTotalMinutes} minutes.'); | |
| } else { | |
| print( | |
| '\nCongratulations! You met the minimum work time. ' | |
| 'You have ${netTotalMinutes - requiredWorkMinutes} minutes extra.', | |
| ); | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment