cron_describer 0.1.0 → 0.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.
- checksums.yaml +4 -4
- data/README.md +104 -8
- data/lib/cron_describer/version.rb +1 -1
- data/lib/cron_describer.rb +178 -12
- metadata +3 -7
- data/cron_describer.gemspec +0 -34
    
        checksums.yaml
    CHANGED
    
    | @@ -1,7 +1,7 @@ | |
| 1 1 | 
             
            ---
         | 
| 2 2 | 
             
            SHA256:
         | 
| 3 | 
            -
              metadata.gz:  | 
| 4 | 
            -
              data.tar.gz:  | 
| 3 | 
            +
              metadata.gz: c483e3538e13ede9eaafdcae76e23a7e7f86d43a541aedc31d7062dec2d2b5b1
         | 
| 4 | 
            +
              data.tar.gz: 65dec9f33dd2a62eb12c849e00cfc1edbe20e29c7966f5ec77590aaf5b1f854d
         | 
| 5 5 | 
             
            SHA512:
         | 
| 6 | 
            -
              metadata.gz:  | 
| 7 | 
            -
              data.tar.gz:  | 
| 6 | 
            +
              metadata.gz: 0eea700d69154e7dd5fff5de279d335b1294c8029852fd57d599e6134a85435337762f5519c53770ec4d11253f1933691526a387ff647cd7ade867bff7ca1c7b
         | 
| 7 | 
            +
              data.tar.gz: 0b1854d853eb6a94c709d2f4437f141df0a006944da79fa8377b1cd25028072d579d73339f80af858df42785bee924f11d92361794ba20a413a45f8475525689
         | 
    
        data/README.md
    CHANGED
    
    | @@ -1,6 +1,6 @@ | |
| 1 1 | 
             
            # CronDescriber
         | 
| 2 2 |  | 
| 3 | 
            -
            CronDescriber is a  | 
| 3 | 
            +
            CronDescriber is a Ruby gem that converts cron schedule strings into human-readable time descriptions. It supports the full cron syntax including ranges, lists, step values, and provides comprehensive input validation with meaningful error messages.
         | 
| 4 4 |  | 
| 5 5 | 
             
            ## Installation
         | 
| 6 6 |  | 
| @@ -22,21 +22,117 @@ Or install it yourself as: | |
| 22 22 | 
             
            $ gem install cron_describer
         | 
| 23 23 | 
             
            ```
         | 
| 24 24 |  | 
| 25 | 
            -
             | 
| 26 25 | 
             
            ## Usage
         | 
| 27 26 |  | 
| 28 | 
            -
             | 
| 27 | 
            +
            ### Basic Examples
         | 
| 29 28 |  | 
| 30 29 | 
             
            ```ruby
         | 
| 31 30 | 
             
            require 'cron_describer'
         | 
| 32 31 |  | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 32 | 
            +
            # Simple time
         | 
| 33 | 
            +
            CronDescriber.parse("30 6 * * *")
         | 
| 34 | 
            +
            # => "At 6:30 AM"
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            # Every day at midnight
         | 
| 37 | 
            +
            CronDescriber.parse("0 0 * * *")
         | 
| 38 | 
            +
            # => "At 12:00 AM"
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            # Afternoon time
         | 
| 41 | 
            +
            CronDescriber.parse("15 14 * * *")
         | 
| 42 | 
            +
            # => "At 2:15 PM"
         | 
| 43 | 
            +
            ```
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            ### Advanced Cron Patterns
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            #### Step Values
         | 
| 48 | 
            +
            ```ruby
         | 
| 49 | 
            +
            # Every 5 minutes
         | 
| 50 | 
            +
            CronDescriber.parse("*/5 * * * *")
         | 
| 51 | 
            +
            # => "Every 5 minutes"
         | 
| 52 | 
            +
             | 
| 53 | 
            +
            # Every 2 hours
         | 
| 54 | 
            +
            CronDescriber.parse("0 */2 * * *")
         | 
| 55 | 
            +
            # => "Every 2 hours"
         | 
| 56 | 
            +
             | 
| 57 | 
            +
            # Every 3 months on the 1st
         | 
| 58 | 
            +
            CronDescriber.parse("0 0 1 */3 *")
         | 
| 59 | 
            +
            # => "At 12:00 AM, on day 1 of the month, every 3 months"
         | 
| 60 | 
            +
            ```
         | 
| 61 | 
            +
             | 
| 62 | 
            +
            #### Ranges
         | 
| 63 | 
            +
            ```ruby
         | 
| 64 | 
            +
            # Weekdays (Monday through Friday)
         | 
| 65 | 
            +
            CronDescriber.parse("0 9 * * 1-5")
         | 
| 66 | 
            +
            # => "At 9:00 AM, only on Monday through Friday"
         | 
| 67 | 
            +
             | 
| 68 | 
            +
            # Summer months
         | 
| 69 | 
            +
            CronDescriber.parse("0 12 1 6-8 *")
         | 
| 70 | 
            +
            # => "At 12:00 PM, on day 1 of the month, June through August"
         | 
| 71 | 
            +
            ```
         | 
| 72 | 
            +
             | 
| 73 | 
            +
            #### Lists
         | 
| 74 | 
            +
            ```ruby
         | 
| 75 | 
            +
            # Specific days of the week
         | 
| 76 | 
            +
            CronDescriber.parse("0 9 * * 1,3,5")
         | 
| 77 | 
            +
            # => "At 9:00 AM, only on Monday, Wednesday, Friday"
         | 
| 78 | 
            +
             | 
| 79 | 
            +
            # Quarter hours
         | 
| 80 | 
            +
            CronDescriber.parse("0,15,30,45 * * * *")
         | 
| 81 | 
            +
            # => "At 0, 15, 30, 45 minutes past the hour"
         | 
| 82 | 
            +
             | 
| 83 | 
            +
            # Multiple specific hours
         | 
| 84 | 
            +
            CronDescriber.parse("0 9,13,17 * * *")
         | 
| 85 | 
            +
            # => "At 9:00 AM, 1:00 PM, 5:00 PM"
         | 
| 86 | 
            +
            ```
         | 
| 87 | 
            +
             | 
| 88 | 
            +
            #### Wildcard Patterns
         | 
| 89 | 
            +
            ```ruby
         | 
| 90 | 
            +
            # Every minute
         | 
| 91 | 
            +
            CronDescriber.parse("* * * * *")
         | 
| 92 | 
            +
            # => "Every minute"
         | 
| 93 | 
            +
             | 
| 94 | 
            +
            # Every minute during 9 AM
         | 
| 95 | 
            +
            CronDescriber.parse("* 9 * * *")
         | 
| 96 | 
            +
            # => "Every minute during 9:00 AM"
         | 
| 37 97 | 
             
            ```
         | 
| 38 98 |  | 
| 39 | 
            -
             | 
| 99 | 
            +
            ## Supported Cron Features
         | 
| 100 | 
            +
             | 
| 101 | 
            +
            - ✅ **Standard 5-field format**: `minute hour day_of_month month day_of_week`
         | 
| 102 | 
            +
            - ✅ **Wildcards**: `*` for any value
         | 
| 103 | 
            +
            - ✅ **Step values**: `*/5` (every 5), `10-50/5` (every 5 from 10 to 50)
         | 
| 104 | 
            +
            - ✅ **Ranges**: `1-5` (1 through 5), `MON-FRI`
         | 
| 105 | 
            +
            - ✅ **Lists**: `1,3,5` (values 1, 3, and 5)
         | 
| 106 | 
            +
            - ✅ **Day of week**: Both `0` and `7` supported for Sunday
         | 
| 107 | 
            +
            - ✅ **12-hour time format**: Proper AM/PM conversion
         | 
| 108 | 
            +
            - ✅ **Input validation**: Comprehensive field validation with helpful error messages
         | 
| 109 | 
            +
            - ✅ **Error handling**: Graceful handling of malformed cron expressions
         | 
| 110 | 
            +
             | 
| 111 | 
            +
            ## Field Ranges
         | 
| 112 | 
            +
             | 
| 113 | 
            +
            - **Minute**: 0-59
         | 
| 114 | 
            +
            - **Hour**: 0-23 (converted to 12-hour AM/PM format in output)
         | 
| 115 | 
            +
            - **Day of Month**: 1-31
         | 
| 116 | 
            +
            - **Month**: 1-12
         | 
| 117 | 
            +
            - **Day of Week**: 0-7 (0 and 7 both represent Sunday)
         | 
| 118 | 
            +
             | 
| 119 | 
            +
            ## Error Handling
         | 
| 120 | 
            +
             | 
| 121 | 
            +
            The gem provides detailed error messages for invalid input:
         | 
| 122 | 
            +
             | 
| 123 | 
            +
            ```ruby
         | 
| 124 | 
            +
            # Invalid minute value
         | 
| 125 | 
            +
            CronDescriber.parse("60 12 * * *")
         | 
| 126 | 
            +
            # => CronDescriber::Error: Invalid minute field: 60
         | 
| 127 | 
            +
             | 
| 128 | 
            +
            # Wrong number of fields
         | 
| 129 | 
            +
            CronDescriber.parse("30 6 1")
         | 
| 130 | 
            +
            # => CronDescriber::Error: Invalid cron format. Expected 5 fields (minute hour day_of_month month day_of_week)
         | 
| 131 | 
            +
             | 
| 132 | 
            +
            # Empty input
         | 
| 133 | 
            +
            CronDescriber.parse("")
         | 
| 134 | 
            +
            # => CronDescriber::Error: Cron schedule cannot be nil or empty
         | 
| 135 | 
            +
            ```
         | 
| 40 136 |  | 
| 41 137 | 
             
            ## Development
         | 
| 42 138 |  | 
    
        data/lib/cron_describer.rb
    CHANGED
    
    | @@ -5,22 +5,178 @@ require_relative "cron_describer/version" | |
| 5 5 | 
             
            module CronDescriber
         | 
| 6 6 | 
             
              class Error < StandardError; end
         | 
| 7 7 |  | 
| 8 | 
            -
              def self. | 
| 9 | 
            -
                 | 
| 8 | 
            +
              def self.ordinalize(number)
         | 
| 9 | 
            +
                num = number.to_i
         | 
| 10 | 
            +
                case num % 100
         | 
| 11 | 
            +
                when 11, 12, 13
         | 
| 12 | 
            +
                  "#{num}th"
         | 
| 13 | 
            +
                else
         | 
| 14 | 
            +
                  case num % 10
         | 
| 15 | 
            +
                  when 1
         | 
| 16 | 
            +
                    "#{num}st"
         | 
| 17 | 
            +
                  when 2
         | 
| 18 | 
            +
                    "#{num}nd"
         | 
| 19 | 
            +
                  when 3
         | 
| 20 | 
            +
                    "#{num}rd"
         | 
| 21 | 
            +
                  else
         | 
| 22 | 
            +
                    "#{num}th"
         | 
| 23 | 
            +
                  end
         | 
| 24 | 
            +
                end
         | 
| 25 | 
            +
              end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
              def self.parse_field(field, field_type)
         | 
| 28 | 
            +
                return "*" if field == "*"
         | 
| 29 | 
            +
                
         | 
| 30 | 
            +
                # Handle step values (e.g., "*/5", "10-30/5")
         | 
| 31 | 
            +
                if field.include?("/")
         | 
| 32 | 
            +
                  base, step = field.split("/")
         | 
| 33 | 
            +
                  step_val = step.to_i
         | 
| 34 | 
            +
                  
         | 
| 35 | 
            +
                  if base == "*"
         | 
| 36 | 
            +
                    case field_type
         | 
| 37 | 
            +
                    when :minute
         | 
| 38 | 
            +
                      return "every #{step_val} minutes"
         | 
| 39 | 
            +
                    when :hour
         | 
| 40 | 
            +
                      return "every #{step_val} hours"
         | 
| 41 | 
            +
                    when :day_of_month
         | 
| 42 | 
            +
                      return "every #{step_val} days"
         | 
| 43 | 
            +
                    when :month
         | 
| 44 | 
            +
                      return "every #{step_val} months"
         | 
| 45 | 
            +
                    when :day_of_week
         | 
| 46 | 
            +
                      return "every #{step_val} days of the week"
         | 
| 47 | 
            +
                    end
         | 
| 48 | 
            +
                  elsif base.include?("-")
         | 
| 49 | 
            +
                    start_val, end_val = base.split("-").map(&:to_i)
         | 
| 50 | 
            +
                    case field_type
         | 
| 51 | 
            +
                    when :minute
         | 
| 52 | 
            +
                      return "every #{step_val} minutes from #{start_val} to #{end_val}"
         | 
| 53 | 
            +
                    when :hour
         | 
| 54 | 
            +
                      return "every #{step_val} hours from #{start_val} to #{end_val}"
         | 
| 55 | 
            +
                    else
         | 
| 56 | 
            +
                      return "every #{step_val} from #{start_val} to #{end_val}"
         | 
| 57 | 
            +
                    end
         | 
| 58 | 
            +
                  end
         | 
| 59 | 
            +
                end
         | 
| 60 | 
            +
                
         | 
| 61 | 
            +
                # Handle ranges (e.g., "1-5")
         | 
| 62 | 
            +
                if field.include?("-") && !field.include?("/")
         | 
| 63 | 
            +
                  start_val, end_val = field.split("-").map(&:to_i)
         | 
| 64 | 
            +
                  case field_type
         | 
| 65 | 
            +
                  when :day_of_week
         | 
| 66 | 
            +
                    days = {0 => "Sunday", 1 => "Monday", 2 => "Tuesday", 3 => "Wednesday", 4 => "Thursday", 5 => "Friday", 6 => "Saturday", 7 => "Sunday"}
         | 
| 67 | 
            +
                    return "#{days[start_val]} through #{days[end_val]}"
         | 
| 68 | 
            +
                  when :month
         | 
| 69 | 
            +
                    months = {1 => "January", 2 => "February", 3 => "March", 4 => "April", 5 => "May", 6 => "June", 
         | 
| 70 | 
            +
                              7 => "July", 8 => "August", 9 => "September", 10 => "October", 11 => "November", 12 => "December"}
         | 
| 71 | 
            +
                    return "#{months[start_val]} through #{months[end_val]}"
         | 
| 72 | 
            +
                  else
         | 
| 73 | 
            +
                    return "#{start_val}-#{end_val}"
         | 
| 74 | 
            +
                  end
         | 
| 75 | 
            +
                end
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                # Handle lists (e.g., "0,15,30,45")
         | 
| 78 | 
            +
                if field.include?(",")
         | 
| 79 | 
            +
                  values = field.split(",").map(&:to_i)
         | 
| 80 | 
            +
                  case field_type
         | 
| 81 | 
            +
                  when :day_of_week
         | 
| 82 | 
            +
                    days = {0 => "Sunday", 1 => "Monday", 2 => "Tuesday", 3 => "Wednesday", 4 => "Thursday", 5 => "Friday", 6 => "Saturday", 7 => "Sunday"}
         | 
| 83 | 
            +
                    day_names = values.map { |v| days[v] }.compact
         | 
| 84 | 
            +
                    return day_names.join(", ")
         | 
| 85 | 
            +
                  when :hour
         | 
| 86 | 
            +
                    return values.map { |v| 
         | 
| 87 | 
            +
                      display_hour = v > 12 ? v - 12 : (v == 0 ? 12 : v)
         | 
| 88 | 
            +
                      "#{display_hour}:00 #{v >= 12 ? 'PM' : 'AM'}"
         | 
| 89 | 
            +
                    }.join(", ")
         | 
| 90 | 
            +
                  when :minute
         | 
| 91 | 
            +
                    return values.join(", ")
         | 
| 92 | 
            +
                  else
         | 
| 93 | 
            +
                    return values.join(", ")
         | 
| 94 | 
            +
                  end
         | 
| 95 | 
            +
                end
         | 
| 96 | 
            +
             | 
| 97 | 
            +
                field
         | 
| 98 | 
            +
              end
         | 
| 10 99 |  | 
| 11 | 
            -
             | 
| 100 | 
            +
              def self.validate_cron_field(field, min_val, max_val, field_name)
         | 
| 101 | 
            +
                return true if field == "*"
         | 
| 102 | 
            +
                
         | 
| 103 | 
            +
                # Handle step values
         | 
| 104 | 
            +
                if field.include?("/")
         | 
| 105 | 
            +
                  base, step = field.split("/")
         | 
| 106 | 
            +
                  return false if step.to_i <= 0
         | 
| 107 | 
            +
                  return validate_cron_field(base, min_val, max_val, field_name) if base != "*"
         | 
| 108 | 
            +
                  return true
         | 
| 109 | 
            +
                end
         | 
| 110 | 
            +
                
         | 
| 111 | 
            +
                # Handle ranges
         | 
| 112 | 
            +
                if field.include?("-")
         | 
| 113 | 
            +
                  start_val, end_val = field.split("-").map(&:to_i)
         | 
| 114 | 
            +
                  return false if start_val < min_val || end_val > max_val || start_val > end_val
         | 
| 115 | 
            +
                  return true
         | 
| 116 | 
            +
                end
         | 
| 117 | 
            +
                
         | 
| 118 | 
            +
                # Handle lists
         | 
| 119 | 
            +
                if field.include?(",")
         | 
| 120 | 
            +
                  values = field.split(",").map(&:to_i)
         | 
| 121 | 
            +
                  return values.all? { |v| v >= min_val && v <= max_val }
         | 
| 122 | 
            +
                end
         | 
| 123 | 
            +
                
         | 
| 124 | 
            +
                # Handle single values
         | 
| 125 | 
            +
                val = field.to_i
         | 
| 126 | 
            +
                val >= min_val && val <= max_val
         | 
| 127 | 
            +
              end
         | 
| 128 | 
            +
             | 
| 129 | 
            +
              def self.parse(cron_schedule)
         | 
| 130 | 
            +
                raise Error, "Cron schedule cannot be nil or empty" if cron_schedule.nil? || cron_schedule.strip.empty?
         | 
| 131 | 
            +
                
         | 
| 132 | 
            +
                fields = cron_schedule.strip.split(/\s+/)
         | 
| 133 | 
            +
                raise Error, "Invalid cron format. Expected 5 fields (minute hour day_of_month month day_of_week)" unless fields.length == 5
         | 
| 134 | 
            +
                
         | 
| 135 | 
            +
                minute, hour, day_of_month, month, day_of_week = fields
         | 
| 136 | 
            +
                
         | 
| 137 | 
            +
                # Validate each field
         | 
| 138 | 
            +
                raise Error, "Invalid minute field: #{minute}" unless validate_cron_field(minute, 0, 59, "minute")
         | 
| 139 | 
            +
                raise Error, "Invalid hour field: #{hour}" unless validate_cron_field(hour, 0, 23, "hour") 
         | 
| 140 | 
            +
                raise Error, "Invalid day of month field: #{day_of_month}" unless validate_cron_field(day_of_month, 1, 31, "day_of_month")
         | 
| 141 | 
            +
                raise Error, "Invalid month field: #{month}" unless validate_cron_field(month, 1, 12, "month")
         | 
| 142 | 
            +
                raise Error, "Invalid day of week field: #{day_of_week}" unless validate_cron_field(day_of_week, 0, 7, "day_of_week")
         | 
| 143 | 
            +
                
         | 
| 144 | 
            +
                days_of_week = {0 => "Sunday", 1 => "Monday", 2 => "Tuesday", 3 => "Wednesday", 4 => "Thursday", 5 => "Friday", 6 => "Saturday", 7 => "Sunday"}
         | 
| 12 145 |  | 
| 13 146 | 
             
                time_string = ""
         | 
| 14 147 | 
             
                day_string = ""
         | 
| 15 148 | 
             
                month_string = ""
         | 
| 16 149 |  | 
| 17 150 | 
             
                # For time string
         | 
| 18 | 
            -
                if minute == "0" && hour != "*"
         | 
| 19 | 
            -
                  time_string = "At #{hour.to_i}:00 AM"
         | 
| 20 | 
            -
                elsif minute != "*" && hour != "*"
         | 
| 151 | 
            +
                if minute == "0" && hour != "*" && !hour.include?(",") && !hour.include?("-") && !hour.include?("/")
         | 
| 21 152 | 
             
                  hour_val = hour.to_i
         | 
| 22 | 
            -
                  time_string = "At #{hour_val > 12 ? hour_val - 12 : hour_val | 
| 153 | 
            +
                  time_string = "At #{hour_val > 12 ? hour_val - 12 : (hour_val == 0 ? 12 : hour_val)}:00 #{hour_val >= 12 ? 'PM' : 'AM'}"
         | 
| 154 | 
            +
                elsif minute != "*" && hour != "*" && !minute.include?(",") && !hour.include?(",") && !hour.include?("-") && !hour.include?("/") && !minute.include?("-") && !minute.include?("/")
         | 
| 155 | 
            +
                  hour_val = hour.to_i
         | 
| 156 | 
            +
                  display_hour = hour_val > 12 ? hour_val - 12 : (hour_val == 0 ? 12 : hour_val)
         | 
| 157 | 
            +
                  time_string = "At #{display_hour}:#{minute.to_i.to_s.rjust(2, '0')} #{hour_val >= 12 ? 'PM' : 'AM'}"
         | 
| 23 158 | 
             
                elsif minute != "*" && hour == "*"
         | 
| 159 | 
            +
                  parsed_minute = parse_field(minute, :minute)
         | 
| 160 | 
            +
                  if parsed_minute.include?("every")
         | 
| 161 | 
            +
                    time_string = "#{parsed_minute.capitalize}"
         | 
| 162 | 
            +
                  elsif minute.include?(",")
         | 
| 163 | 
            +
                    time_string = "At #{parsed_minute} minutes past the hour"
         | 
| 164 | 
            +
                  else
         | 
| 165 | 
            +
                    time_string = "At #{minute.to_i} minutes past the hour"
         | 
| 166 | 
            +
                  end
         | 
| 167 | 
            +
                elsif minute == "*" && hour != "*" && !hour.include?(",") && !hour.include?("-") && !hour.include?("/")
         | 
| 168 | 
            +
                  hour_val = hour.to_i
         | 
| 169 | 
            +
                  display_hour = hour_val > 12 ? hour_val - 12 : (hour_val == 0 ? 12 : hour_val)
         | 
| 170 | 
            +
                  time_string = "Every minute during #{display_hour}:00 #{hour_val >= 12 ? 'PM' : 'AM'}"
         | 
| 171 | 
            +
                elsif minute == "*" && hour == "*"
         | 
| 172 | 
            +
                  time_string = "Every minute"
         | 
| 173 | 
            +
                elsif minute == "0" && hour.include?("/")
         | 
| 174 | 
            +
                  parsed_hour = parse_field(hour, :hour)
         | 
| 175 | 
            +
                  time_string = "#{parsed_hour.capitalize}"
         | 
| 176 | 
            +
                elsif minute == "0" && hour.include?(",")
         | 
| 177 | 
            +
                  parsed_hour = parse_field(hour, :hour)
         | 
| 178 | 
            +
                  time_string = "At #{parsed_hour}"
         | 
| 179 | 
            +
                elsif minute != "*" && hour.include?("-") && !minute.include?(",") && !minute.include?("-") && !minute.include?("/")
         | 
| 24 180 | 
             
                  time_string = "At #{minute.to_i} minutes past the hour"
         | 
| 25 181 | 
             
                end
         | 
| 26 182 |  | 
| @@ -30,15 +186,25 @@ module CronDescriber | |
| 30 186 | 
             
                elsif day_of_week =~ /\d#(\d)/
         | 
| 31 187 | 
             
                  week_num = $1
         | 
| 32 188 | 
             
                  day_num = day_of_week[0].to_i
         | 
| 33 | 
            -
                  day_string = ", on the #{week_num | 
| 189 | 
            +
                  day_string = ", on the #{ordinalize(week_num)} #{days_of_week[day_num]} of the month"
         | 
| 34 190 | 
             
                elsif day_of_week != "*"
         | 
| 35 | 
            -
                   | 
| 36 | 
            -
                   | 
| 191 | 
            +
                  parsed_dow = parse_field(day_of_week, :day_of_week)
         | 
| 192 | 
            +
                  if parsed_dow.include?(",") || parsed_dow.include?("through")
         | 
| 193 | 
            +
                    day_string = ", only on #{parsed_dow}"
         | 
| 194 | 
            +
                  else
         | 
| 195 | 
            +
                    day_num = day_of_week.to_i
         | 
| 196 | 
            +
                    day_string = ", only on #{days_of_week[day_num]}"
         | 
| 197 | 
            +
                  end
         | 
| 37 198 | 
             
                end
         | 
| 38 199 |  | 
| 39 200 | 
             
                # For month string
         | 
| 40 | 
            -
                if month != "*" | 
| 41 | 
            -
                   | 
| 201 | 
            +
                if month != "*"
         | 
| 202 | 
            +
                  parsed_month = parse_field(month, :month)
         | 
| 203 | 
            +
                  if parsed_month != month && parsed_month != "*"
         | 
| 204 | 
            +
                    month_string = ", #{parsed_month}"
         | 
| 205 | 
            +
                  elsif month.include?("/") && month != "*/1"
         | 
| 206 | 
            +
                    month_string = ", #{parsed_month}"
         | 
| 207 | 
            +
                  end
         | 
| 42 208 | 
             
                end
         | 
| 43 209 |  | 
| 44 210 | 
             
                return "#{time_string}#{day_string}#{month_string}"
         | 
    
        metadata
    CHANGED
    
    | @@ -1,14 +1,13 @@ | |
| 1 1 | 
             
            --- !ruby/object:Gem::Specification
         | 
| 2 2 | 
             
            name: cron_describer
         | 
| 3 3 | 
             
            version: !ruby/object:Gem::Version
         | 
| 4 | 
            -
              version: 0. | 
| 4 | 
            +
              version: 0.2.0
         | 
| 5 5 | 
             
            platform: ruby
         | 
| 6 6 | 
             
            authors:
         | 
| 7 7 | 
             
            - Aleksander Lopez Yazikov
         | 
| 8 | 
            -
            autorequire:
         | 
| 9 8 | 
             
            bindir: exe
         | 
| 10 9 | 
             
            cert_chain: []
         | 
| 11 | 
            -
            date:  | 
| 10 | 
            +
            date: 1980-01-02 00:00:00.000000000 Z
         | 
| 12 11 | 
             
            dependencies:
         | 
| 13 12 | 
             
            - !ruby/object:Gem::Dependency
         | 
| 14 13 | 
             
              name: rspec
         | 
| @@ -37,7 +36,6 @@ files: | |
| 37 36 | 
             
            - LICENSE.txt
         | 
| 38 37 | 
             
            - README.md
         | 
| 39 38 | 
             
            - Rakefile
         | 
| 40 | 
            -
            - cron_describer.gemspec
         | 
| 41 39 | 
             
            - lib/cron_describer.rb
         | 
| 42 40 | 
             
            - lib/cron_describer/version.rb
         | 
| 43 41 | 
             
            - sig/cron_describer.rbs
         | 
| @@ -48,7 +46,6 @@ metadata: | |
| 48 46 | 
             
              homepage_uri: https://github.com/logicalgroove/cron_describer
         | 
| 49 47 | 
             
              source_code_uri: https://github.com/logicalgroove/cron_describer
         | 
| 50 48 | 
             
              changelog_uri: https://github.com/logicalgroove/cron_describer
         | 
| 51 | 
            -
            post_install_message:
         | 
| 52 49 | 
             
            rdoc_options: []
         | 
| 53 50 | 
             
            require_paths:
         | 
| 54 51 | 
             
            - lib
         | 
| @@ -63,8 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement | |
| 63 60 | 
             
                - !ruby/object:Gem::Version
         | 
| 64 61 | 
             
                  version: '0'
         | 
| 65 62 | 
             
            requirements: []
         | 
| 66 | 
            -
            rubygems_version: 3. | 
| 67 | 
            -
            signing_key:
         | 
| 63 | 
            +
            rubygems_version: 3.6.9
         | 
| 68 64 | 
             
            specification_version: 4
         | 
| 69 65 | 
             
            summary: A gem to convert cron schedule strings into human-readable time
         | 
| 70 66 | 
             
            test_files: []
         | 
    
        data/cron_describer.gemspec
    DELETED
    
    | @@ -1,34 +0,0 @@ | |
| 1 | 
            -
            # frozen_string_literal: true
         | 
| 2 | 
            -
             | 
| 3 | 
            -
            require_relative "lib/cron_describer/version"
         | 
| 4 | 
            -
             | 
| 5 | 
            -
            Gem::Specification.new do |spec|
         | 
| 6 | 
            -
              spec.name = "cron_describer"
         | 
| 7 | 
            -
              spec.version = CronDescriber::VERSION
         | 
| 8 | 
            -
              spec.authors = ["Aleksander Lopez Yazikov"]
         | 
| 9 | 
            -
              spec.email = ["webodessa@gmail.com"]
         | 
| 10 | 
            -
             | 
| 11 | 
            -
              spec.summary = "A gem to convert cron schedule strings into human-readable time"
         | 
| 12 | 
            -
              spec.description = "A Ruby gem that takes a cron schedule string and converts it into a human-readable time description."
         | 
| 13 | 
            -
              spec.homepage = "https://github.com/logicalgroove/cron_describer"
         | 
| 14 | 
            -
              spec.license = "MIT"
         | 
| 15 | 
            -
              spec.required_ruby_version = ">= 2.6.0"
         | 
| 16 | 
            -
             | 
| 17 | 
            -
              spec.metadata["homepage_uri"] = spec.homepage
         | 
| 18 | 
            -
              spec.metadata["source_code_uri"] = "https://github.com/logicalgroove/cron_describer"
         | 
| 19 | 
            -
              spec.metadata["changelog_uri"] = "https://github.com/logicalgroove/cron_describer"
         | 
| 20 | 
            -
             | 
| 21 | 
            -
              # Specify which files should be added to the gem when it is released.
         | 
| 22 | 
            -
              # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
         | 
| 23 | 
            -
              spec.files = Dir.chdir(__dir__) do
         | 
| 24 | 
            -
                `git ls-files -z`.split("\x0").reject do |f|
         | 
| 25 | 
            -
                  (File.expand_path(f) == __FILE__) ||
         | 
| 26 | 
            -
                    f.start_with?(*%w[bin/ test/ spec/ features/ .git .circleci appveyor Gemfile])
         | 
| 27 | 
            -
                end
         | 
| 28 | 
            -
              end
         | 
| 29 | 
            -
              spec.bindir = "exe"
         | 
| 30 | 
            -
              spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
         | 
| 31 | 
            -
              spec.require_paths = ["lib"]
         | 
| 32 | 
            -
             | 
| 33 | 
            -
              spec.add_development_dependency "rspec", "~> 3.0"
         | 
| 34 | 
            -
            end
         |