Feature #5458 » 5458-use_time_in_issue_start_and_due_date_2.3_stable_V9_3.diff
| app/controllers/issues_controller.rb (working copy) | ||
|---|---|---|
| 425 | 425 | 
    @issue.project ||= @issue.allowed_target_projects.first  | 
| 426 | 426 | 
    end  | 
| 427 | 427 | 
    @issue.author ||= User.current  | 
| 428 | 
        @issue.start_date ||= Date.today if Setting.default_issue_start_date_to_creation_date?
   | 
|
| 428 | 
        @issue.start_date ||= DateTime.now if Setting.default_issue_start_date_to_creation_date?
   | 
|
| 429 | 429 | |
| 430 | 430 | 
        attrs = (params[:issue] || {}).deep_dup
   | 
| 431 | 431 | 
    if action_name == 'new' && params[:was_default_status] == attrs[:status_id]  | 
| app/helpers/application_helper.rb (working copy) | ||
|---|---|---|
| 291 | 291 | 
    end  | 
| 292 | 292 | 
    end  | 
| 293 | 293 | 
     | 
| 294 | 
      def time_select_tag( name, stime, options = {} )
   | 
|
| 295 | 
    time = stime.to_time(:utc)  | 
|
| 296 | 
    if time.nil?  | 
|
| 297 | 
          selected = {:hour => '', :min => ''}
   | 
|
| 298 | 
    else  | 
|
| 299 | 
    zone = User.current.time_zone  | 
|
| 300 | 
    time = zone ? time.in_time_zone(zone) : (time.utc? ? time.localtime : time)  | 
|
| 301 | 
          selected = {:hour => time.hour, :min => time.min}
   | 
|
| 302 | 
    end  | 
|
| 303 | 
     | 
|
| 304 | 
    out = ''  | 
|
| 305 | 
     | 
|
| 306 | 
    if options[:required]  | 
|
| 307 | 
    hours = []  | 
|
| 308 | 
    mins = []  | 
|
| 309 | 
    else  | 
|
| 310 | 
    hours = [['', '']]  | 
|
| 311 | 
    mins = [['', '']]  | 
|
| 312 | 
    end  | 
|
| 313 | 
     | 
|
| 314 | 
        hours += (0..23).map{|i| ['%02d' % i, i] } # Zero pad
   | 
|
| 315 | 
    out << select_tag(  | 
|
| 316 | 
          "#{name}[hour]",
   | 
|
| 317 | 
    options_for_select( hours, selected[:hour] ),  | 
|
| 318 | 
    :style => 'min-width: 10px;max-width: 50px;'  | 
|
| 319 | 
    )  | 
|
| 320 | 
     | 
|
| 321 | 
    out << ':'  | 
|
| 322 | 
        mins += (0..59).map{|i| ['%02d' % i, i] } # Zero pad
   | 
|
| 323 | 
    out << select_tag(  | 
|
| 324 | 
          "#{name}[minute]",
   | 
|
| 325 | 
    options_for_select( mins, selected[:min] ),  | 
|
| 326 | 
    :style => 'min-width: 10px;max-width: 50px;'  | 
|
| 327 | 
    )  | 
|
| 328 | 
    end  | 
|
| 329 | 
     | 
|
| 294 | 330 | 
      def project_tree_options_for_select(projects, options = {})
   | 
| 295 | 331 | 
    s = ''  | 
| 296 | 332 | 
    project_tree(projects) do |project, level|  | 
| app/helpers/queries_helper.rb (working copy) | ||
|---|---|---|
| 151 | 151 | 
            value.to_s(issue) {|other| link_to_issue(other, :subject => false, :tracker => false)}.html_safe,
   | 
| 152 | 152 | 
    :class => value.css_classes_for(issue))  | 
| 153 | 153 | 
    else  | 
| 154 | 
    format_object(value)  | 
|
| 154 | 
    case value.class.name  | 
|
| 155 | 
    when 'Time'  | 
|
| 156 | 
    if ( column.name == :start_date or column.name == :due_date ) and  | 
|
| 157 | 
                      ( !issue.project.use_datetime_for_issues or value.strftime('%H%M')=='0000' )
   | 
|
| 158 | 
    format_date(value)  | 
|
| 159 | 
    else  | 
|
| 160 | 
    format_time(value)  | 
|
| 161 | 
    end  | 
|
| 162 | 
    else  | 
|
| 163 | 
    format_object(value)  | 
|
| 164 | 
    end  | 
|
| 155 | 165 | 
    end  | 
| 156 | 166 | 
    end  | 
| 157 | 167 | 
     | 
| app/models/issue.rb (working copy) | ||
|---|---|---|
| 61 | 61 | 
    DONE_RATIO_OPTIONS = %w(issue_field issue_status)  | 
| 62 | 62 | 
     | 
| 63 | 63 | 
    attr_reader :current_journal  | 
| 64 | 
    attr_accessor :start_time  | 
|
| 65 | 
    attr_accessor :due_time  | 
|
| 66 | 
     | 
|
| 64 | 67 | 
    delegate :notes, :notes=, :private_notes, :private_notes=, :to => :current_journal, :allow_nil => true  | 
| 65 | 68 | 
     | 
| 66 | 69 | 
    validates_presence_of :subject, :priority, :project, :tracker, :author, :status  | 
| ... | ... | |
| 68 | 71 | 
    validates_length_of :subject, :maximum => 255  | 
| 69 | 72 | 
    validates_inclusion_of :done_ratio, :in => 0..100  | 
| 70 | 73 | 
      validates :estimated_hours, :numericality => {:greater_than_or_equal_to => 0, :allow_nil => true, :message => :invalid}
   | 
| 71 | 
    validates :start_date, :date => true  | 
|
| 72 | 
    validates :due_date, :date => true  | 
|
| 74 | 
      #validates :start_date, :date => true
   | 
|
| 75 | 
      #validates :due_date, :date => true
   | 
|
| 73 | 76 | 
    validate :validate_issue, :validate_required_fields  | 
| 74 | 77 | 
     | 
| 75 | 78 | 
      scope :visible, lambda {|*args|
   | 
| ... | ... | |
| 91 | 94 | |
| 92 | 95 | 
    before_validation :clear_disabled_fields  | 
| 93 | 96 | 
    before_create :default_assign  | 
| 94 | 
    before_save :close_duplicates, :update_done_ratio_from_issue_status,  | 
|
| 95 | 
    :force_updated_on_change, :update_closed_on, :set_assigned_to_was  | 
|
| 97 | 
    #Note very well - before_save runs for both updates AND creations (also, before_create is called after before_save)  | 
|
| 98 | 
    before_save :close_duplicates, :update_done_ratio_from_issue_status,  | 
|
| 99 | 
    :force_updated_on_change, :update_closed_on, :set_assigned_to_was, :add_start_and_due_time  | 
|
| 96 | 100 | 
      after_save {|issue| issue.send :after_project_change if !issue.id_changed? && issue.project_id_changed?}
   | 
| 97 | 101 | 
    after_save :reschedule_following_issues, :update_nested_set_attributes,  | 
| 98 | 102 | 
    :update_parent_attributes, :create_journal  | 
| ... | ... | |
| 361 | 365 | 
    'subject',  | 
| 362 | 366 | 
    'description',  | 
| 363 | 367 | 
    'start_date',  | 
| 368 | 
    'start_time',  | 
|
| 364 | 369 | 
    'due_date',  | 
| 370 | 
    'due_time',  | 
|
| 365 | 371 | 
    'done_ratio',  | 
| 366 | 372 | 
    'estimated_hours',  | 
| 367 | 373 | 
    'custom_field_values',  | 
| ... | ... | |
| 454 | 460 | 
     | 
| 455 | 461 | 
    # mass-assignment security bypass  | 
| 456 | 462 | 
    assign_attributes attrs, :without_protection => true  | 
| 463 | 
     | 
|
| 464 | 
    # Helper to make sure that when we load in the time it takes into account that it is supplied localised and must be converted back to utc.  | 
|
| 465 | 
    def load_localised_time(date, time, time_zone)  | 
|
| 466 | 
          localised_date = {:year => date.year, :month => date.month, :day => date.day}
   | 
|
| 467 | 
          localised_datetime = date.in_time_zone(time_zone).change({:hour => time['hour'].to_i, :min => time['minute'].to_i})
   | 
|
| 468 | 
    return localised_datetime.change(localised_date).utc  | 
|
| 469 | 
    end  | 
|
| 470 | 
     | 
|
| 471 | 
        if (start_time = attrs.delete('start_time')) && safe_attribute?('start_time') && self.start_date.is_a?(Time)
   | 
|
| 472 | 
    self.start_date = load_localised_time(self.start_date, start_time, user.time_zone)  | 
|
| 473 | 
    end  | 
|
| 474 | 
     | 
|
| 475 | 
        if (due_time = attrs.delete('due_time')) && safe_attribute?('due_time') && self.due_date.is_a?(Time)
   | 
|
| 476 | 
    self.due_date = load_localised_time(self.due_date, due_time, user.time_zone)  | 
|
| 477 | 
    end  | 
|
| 457 | 478 | 
    end  | 
| 458 | 479 | 
     | 
| 459 | 480 | 
    def disabled_core_fields  | 
| ... | ... | |
| 1388 | 1409 | 
    end  | 
| 1389 | 1410 | 
    end  | 
| 1390 | 1411 | 
     | 
| 1412 | 
    # Callback on start and due time  | 
|
| 1413 | 
    def add_start_and_due_time  | 
|
| 1414 | 
    return if not project.use_datetime_for_issues  | 
|
| 1415 | 
     | 
|
| 1416 | 
    # Not sure if this is a hack or not, but it works :)  | 
|
| 1417 | 
    time_zone = User.current.time_zone  | 
|
| 1418 | 
    system_time_zone = Time.zone  | 
|
| 1419 | 
    if time_zone  | 
|
| 1420 | 
    Time.zone = time_zone  | 
|
| 1421 | 
    end  | 
|
| 1422 | 
     | 
|
| 1423 | 
    if st=start_time and sd=start_date  | 
|
| 1424 | 
    if st['hour'].to_i >= 0 or st['minute'].to_i >= 0  | 
|
| 1425 | 
            self.start_date = Time.zone.parse( "#{sd.year}.#{sd.month}.#{sd.day} #{st['hour']}:#{st['minute']}:00" ).utc # Parse in as local but save as UTC
   | 
|
| 1426 | 
    end  | 
|
| 1427 | 
    end  | 
|
| 1428 | 
     | 
|
| 1429 | 
    if dt=due_time and dd=due_date  | 
|
| 1430 | 
    if dt['hour'].to_i >= 0 or dt['minute'].to_i >= 0  | 
|
| 1431 | 
            self.due_date = Time.zone.parse( "#{dd.year}.#{dd.month}.#{dd.day} #{dt['hour']}:#{dt['minute']}:00").utc # Parse in as local but save as UTC
   | 
|
| 1432 | 
    end  | 
|
| 1433 | 
    end  | 
|
| 1434 | 
     | 
|
| 1435 | 
    # Since we fudged the timezone to get the values parsing in okay, let's reset it to the system timezone.  | 
|
| 1436 | 
    Time.zone = system_time_zone  | 
|
| 1437 | 
    end  | 
|
| 1438 | 
     | 
|
| 1391 | 1439 | 
    # Default assignment based on category  | 
| 1392 | 1440 | 
    def default_assign  | 
| 1393 | 1441 | 
    if assigned_to.nil? && category && category.assigned_to  | 
| app/models/project.rb (working copy) | ||
|---|---|---|
| 549 | 549 | 
    # The earliest start date of a project, based on it's issues and versions  | 
| 550 | 550 | 
    def start_date  | 
| 551 | 551 | 
    @start_date ||= [  | 
| 552 | 
         issues.minimum('start_date'),
   | 
|
| 552 | 
         issues.minimum('start_date').nil? ? nil : issues.minimum('start_date').to_date,
   | 
|
| 553 | 553 | 
         shared_versions.minimum('effective_date'),
   | 
| 554 | 
         Issue.fixed_version(shared_versions).minimum('start_date')
   | 
|
| 554 | 
         Issue.fixed_version(shared_versions).minimum('start_date').nil? ? nil : Issue.fixed_version(shared_versions).minimum('start_date').to_date
   | 
|
| 555 | 555 | 
    ].compact.min  | 
| 556 | 556 | 
    end  | 
| 557 | 557 | 
     | 
| 558 | 558 | 
    # The latest due date of an issue or version  | 
| 559 | 559 | 
    def due_date  | 
| 560 | 560 | 
    @due_date ||= [  | 
| 561 | 
         issues.maximum('due_date'),
   | 
|
| 561 | 
         issues.maximum('due_date').nil? ? nil : issues.maximum('due_date').to_date,
   | 
|
| 562 | 562 | 
         shared_versions.maximum('effective_date'),
   | 
| 563 | 
         Issue.fixed_version(shared_versions).maximum('due_date')
   | 
|
| 563 | 
         Issue.fixed_version(shared_versions).maximum('due_date').nil? ? nil : Issue.fixed_version(shared_versions).maximum('due_date').to_date
   | 
|
| 564 | 564 | 
    ].compact.max  | 
| 565 | 565 | 
    end  | 
| 566 | 566 | 
     | 
| 567 | 567 | 
    def overdue?  | 
| 568 | 
        active? && !due_date.nil? && (due_date < Date.today)
   | 
|
| 568 | 
        active? && !due_date.nil? && (due_date < DateTime.now)
   | 
|
| 569 | 569 | 
    end  | 
| 570 | 570 | 
     | 
| 571 | 571 | 
    # Returns the percent completed for this project, based on the  | 
| ... | ... | |
| 650 | 650 | 
    'description',  | 
| 651 | 651 | 
    'homepage',  | 
| 652 | 652 | 
    'is_public',  | 
| 653 | 
    'use_datetime_for_issues',  | 
|
| 653 | 654 | 
    'identifier',  | 
| 654 | 655 | 
    'custom_field_values',  | 
| 655 | 656 | 
    'custom_fields',  | 
| app/models/version.rb (working copy) | ||
|---|---|---|
| 100 | 100 | 
    if completed_percent == 100  | 
| 101 | 101 | 
    return false  | 
| 102 | 102 | 
    elsif due_date && start_date  | 
| 103 | 
          done_date = start_date + ((due_date - start_date+1)* completed_percent/100).floor
   | 
|
| 103 | 
          done_date = start_date.to_date + ((due_date.to_date - start_date.to_date + 1) * completed_percent/100).floor
   | 
|
| 104 | 104 | 
    return done_date <= Date.today  | 
| 105 | 105 | 
    else  | 
| 106 | 106 | 
    false # No issues so it's not late  | 
| app/views/issues/_attributes.html.erb (working copy) | ||
|---|---|---|
| 48 | 48 | 
     | 
| 49 | 49 | 
    <% if @issue.safe_attribute? 'start_date' %>  | 
| 50 | 50 | 
    <p id="start_date_area">  | 
| 51 | 
      <%= f.text_field(:start_date, :size => 10, :required => @issue.required_attribute?('start_date')) %>
   | 
|
| 51 | 
      <%= f.text_field(:start_date, :value => (@issue.start_date ? localise_date(@issue.start_date).strftime('%Y-%m-%d') : ''), :size => 10, :required => @issue.required_attribute?('start_date')) %>
   | 
|
| 52 | 52 | 
      <%= calendar_for('issue_start_date') if @issue.leaf? %>
   | 
| 53 | 53 | 
    </p>  | 
| 54 | 54 | 
    <% end %>  | 
| 55 | 55 | 
     | 
| 56 | 56 | 
    <% if @issue.safe_attribute? 'due_date' %>  | 
| 57 | 57 | 
    <p id="due_date_area">  | 
| 58 | 
      <%= f.text_field(:due_date, :size => 10, :required => @issue.required_attribute?('due_date')) %>
   | 
|
| 58 | 
      <%= f.text_field(:due_date, :value => (@issue.due_date ? localise_date(@issue.due_date).strftime('%Y-%m-%d') : ''), :size => 10, :required => @issue.required_attribute?('due_date')) %>
   | 
|
| 59 | 59 | 
      <%= calendar_for('issue_due_date') if @issue.leaf? %>
   | 
| 60 | 60 | 
    </p>  | 
| 61 | 61 | 
    <% end %>  | 
| app/views/issues/show.html.erb (working copy) | ||
|---|---|---|
| 47 | 47 | 
    end  | 
| 48 | 48 | 
     | 
| 49 | 49 | 
      unless @issue.disabled_core_fields.include?('start_date')
   | 
| 50 | 
        rows.right l(:field_start_date), format_date(@issue.start_date), :class => 'start-date'
   | 
|
| 50 | 
        rows.right l(:field_start_date), (@project.use_datetime_for_issues ? format_time(@issue.start_date) : format_date(@issue.start_date)), :class => 'start-date'
   | 
|
| 51 | 51 | 
    end  | 
| 52 | 52 | 
      unless @issue.disabled_core_fields.include?('due_date')
   | 
| 53 | 
        rows.right l(:field_due_date), format_date(@issue.due_date), :class => 'due-date'
   | 
|
| 53 | 
        rows.right l(:field_due_date), (@project.use_datetime_for_issues ? format_time(@issue.due_date) : format_date(@issue.due_date)), :class => 'due-date'
   | 
|
| 54 | 54 | 
    end  | 
| 55 | 55 | 
      unless @issue.disabled_core_fields.include?('done_ratio')
   | 
| 56 | 56 | 
        rows.right l(:field_done_ratio), progress_bar(@issue.done_ratio, :width => '80px', :legend => "#{@issue.done_ratio}%"), :class => 'progress'
   | 
| app/views/projects/_form.html.erb (working copy) | ||
|---|---|---|
| 11 | 11 | 
    <% end %></p>  | 
| 12 | 12 | 
    <p><%= f.text_field :homepage, :size => 60 %></p>  | 
| 13 | 13 | 
    <p><%= f.check_box :is_public %></p>  | 
| 14 | 
    <p><%= f.check_box :use_datetime_for_issues %></p>  | 
|
| 14 | 15 | 
     | 
| 15 | 16 | 
    <% unless @project.allowed_parents.compact.empty? %>  | 
| 16 | 17 | 
    <p><%= label(:project, :parent_id, l(:field_parent)) %><%= parent_project_select_tag(@project) %></p>  | 
| config/locales/cs.yml (working copy) | ||
|---|---|---|
| 311 | 311 | 
    field_assigned_to_role: Role přiřaditele  | 
| 312 | 312 | 
    field_text: Textové pole  | 
| 313 | 313 | 
    field_visible: Viditelný  | 
| 314 | 
     | 
|
| 314 | 
    field_use_datetime_for_issues: Použít u tiketů také čas  | 
|
| 315 | 315 | 
    setting_app_title: Název aplikace  | 
| 316 | 316 | 
    setting_app_subtitle: Podtitulek aplikace  | 
| 317 | 317 | 
    setting_welcome_text: Uvítací text  | 
| config/locales/en-GB.yml (working copy) | ||
|---|---|---|
| 311 | 311 | 
    field_assigned_to_role: "Assignee's role"  | 
| 312 | 312 | 
    field_text: Text field  | 
| 313 | 313 | 
    field_visible: Visible  | 
| 314 | 
    field_use_datetime_for_issues: Use time in tickets too  | 
|
| 314 | 315 | 
    field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"  | 
| 315 | 316 | 
     | 
| 316 | 317 | 
    setting_app_title: Application title  | 
| config/locales/en.yml (working copy) | ||
|---|---|---|
| 314 | 314 | 
    field_assigned_to_role: "Assignee's role"  | 
| 315 | 315 | 
    field_text: Text field  | 
| 316 | 316 | 
    field_visible: Visible  | 
| 317 | 
    field_use_datetime_for_issues: Use time in tickets too  | 
|
| 317 | 318 | 
    field_warn_on_leaving_unsaved: "Warn me when leaving a page with unsaved text"  | 
| 318 | 319 | 
    field_issues_visibility: Issues visibility  | 
| 319 | 320 | 
    field_is_private: Private  | 
| config/locales/es.yml (working copy) | ||
|---|---|---|
| 1110 | 1110 | 
    button_hide: Ocultar  | 
| 1111 | 1111 | 
    setting_non_working_week_days: Días no laborables  | 
| 1112 | 1112 | 
    label_in_the_next_days: en los próximos  | 
| 1113 | 
    field_use_datetime_for_issues: Usar hora en prog peticiones  | 
|
| 1113 | 1114 | 
    label_in_the_past_days: en los anteriores  | 
| 1114 | 1115 | 
      label_attribute_of_user: "%{name} del usuario"
   | 
| 1115 | 1116 | 
    text_turning_multiple_off: Si desactiva los valores múltiples, éstos serán eliminados para dejar un único valor por elemento.  | 
| db/migrate/20130531174459_add_time_to_issue_start_date_and_issue_due_date.rb (working copy) | ||
|---|---|---|
| 1 | 
    class AddTimeToIssueStartDateAndIssueDueDate < ActiveRecord::Migration  | 
|
| 2 | 
    def self.up  | 
|
| 3 | 
    change_column :issues, :start_date, :datetime  | 
|
| 4 | 
    change_column :issues, :due_date, :datetime  | 
|
| 5 | 
    end  | 
|
| 6 | 
     | 
|
| 7 | 
    def self.down  | 
|
| 8 | 
    change_column :issues, :start_date, :date  | 
|
| 9 | 
    change_column :issues, :due_date, :date  | 
|
| 10 | 
    end  | 
|
| 11 | 
    end  | 
|
| db/migrate/20130531174549_add_use_datetime_for_issues_to_projects.rb (working copy) | ||
|---|---|---|
| 1 | 
    class AddUseDatetimeForIssuesToProjects < ActiveRecord::Migration  | 
|
| 2 | 
     | 
|
| 3 | 
    def self.up  | 
|
| 4 | 
    add_column :projects, :use_datetime_for_issues, :boolean, :default => false  | 
|
| 5 | 
    end  | 
|
| 6 | 
     | 
|
| 7 | 
    def self.down  | 
|
| 8 | 
    remove_column :projects, :use_datetime_for_issues  | 
|
| 9 | 
    end  | 
|
| 10 | 
     | 
|
| 11 | 
    end  | 
|
| lib/redmine/helpers/calendar.rb (working copy) | ||
|---|---|---|
| 48 | 48 | 
    # Sets calendar events  | 
| 49 | 49 | 
    def events=(events)  | 
| 50 | 50 | 
    @events = events  | 
| 51 | 
            @ending_events_by_days = @events.group_by {|event| event.due_date}
   | 
|
| 52 | 
            @starting_events_by_days = @events.group_by {|event| event.start_date}
   | 
|
| 51 | 
            @ending_events_by_days = @events.group_by {|event| (event.due_date.is_a?(Date) || event.due_date.nil? ? event.due_date : event.due_date.to_date) }
   | 
|
| 52 | 
            @starting_events_by_days = @events.group_by {|event| (event.start_date.is_a?(Date) || event.start_date.nil?  ? event.start_date : event.start_date.to_date) }
   | 
|
| 53 | 53 | 
    end  | 
| 54 | 54 | 
     | 
| 55 | 55 | 
    # Returns events for the given day  | 
| lib/redmine/helpers/gantt.rb (working copy) | ||
|---|---|---|
| 628 | 628 | 
    private  | 
| 629 | 629 | 
     | 
| 630 | 630 | 
    def coordinates(start_date, end_date, progress, zoom=nil)  | 
| 631 | 
    start_date = start_date.to_date if not start_date.nil?  | 
|
| 632 | 
    end_date = end_date.to_date if not end_date.nil?  | 
|
| 633 | 
     | 
|
| 631 | 634 | 
    zoom ||= @zoom  | 
| 632 | 635 | 
            coords = {}
   | 
| 633 | 636 | 
    if start_date && end_date && start_date < self.date_to && end_date > self.date_from  | 
| ... | ... | |
| 672 | 675 | 
    end  | 
| 673 | 676 | 
     | 
| 674 | 677 | 
    def calc_progress_date(start_date, end_date, progress)  | 
| 675 | 
            start_date + (end_date - start_date + 1) * (progress / 100.0)
   | 
|
| 678 | 
            start_date.to_date + (end_date.to_date - start_date.to_date + 1) * (progress / 100.0)
   | 
|
| 676 | 679 | 
    end  | 
| 677 | 680 | 
     | 
| 678 | 681 | 
    # TODO: Sorts a collection of issues by start_date, due_date, id for gantt rendering  | 
| lib/redmine/i18n.rb (working copy) | ||
|---|---|---|
| 52 | 52 | 
          ::I18n.t(str.to_s, :value => value, :locale => lang.to_s.gsub(%r{(.+)\-(.+)$}) { "#{$1}-#{$2.upcase}" })
   | 
| 53 | 53 | 
    end  | 
| 54 | 54 | 
     | 
| 55 | 
    def localise_date(date)  | 
|
| 56 | 
    return if date.nil?  | 
|
| 57 | 
     | 
|
| 58 | 
    zone = User.current.time_zone  | 
|
| 59 | 
    local = zone ? date.in_time_zone(zone) : date  | 
|
| 60 | 
    return local  | 
|
| 61 | 
    end  | 
|
| 62 | 
     | 
|
| 55 | 63 | 
    def format_date(date)  | 
| 56 | 64 | 
    return nil unless date  | 
| 57 | 65 | 
          options = {}
   | 
| lib/redmine/utils.rb (working copy) | ||
|---|---|---|
| 60 | 60 | 
    weeks = days / 7  | 
| 61 | 61 | 
    result = weeks * (7 - non_working_week_days.size)  | 
| 62 | 62 | 
    days_left = days - weeks * 7  | 
| 63 | 
    start_cwday = from.cwday  | 
|
| 63 | 
              start_cwday = from.to_date.cwday
   | 
|
| 64 | 64 | 
    days_left.times do |i|  | 
| 65 | 65 | 
    unless non_working_week_days.include?(((start_cwday + i - 1) % 7) + 1)  | 
| 66 | 66 | 
    result += 1  | 
| ... | ... | |
| 78 | 78 | 
    weeks = working_days / (7 - non_working_week_days.size)  | 
| 79 | 79 | 
    result = weeks * 7  | 
| 80 | 80 | 
    days_left = working_days - weeks * (7 - non_working_week_days.size)  | 
| 81 | 
    cwday = date.cwday  | 
|
| 81 | 
              cwday = date.to_date.cwday
   | 
|
| 82 | 82 | 
    while days_left > 0  | 
| 83 | 83 | 
    cwday += 1  | 
| 84 | 84 | 
    unless non_working_week_days.include?(((cwday - 1) % 7) + 1)  | 
| ... | ... | |
| 94 | 94 | 
     | 
| 95 | 95 | 
    # Returns the date of the first day on or after the given date that is a working day  | 
| 96 | 96 | 
    def next_working_date(date)  | 
| 97 | 
    cwday = date.cwday  | 
|
| 97 | 
            cwday = date.to_date.cwday
   | 
|
| 98 | 98 | 
    days = 0  | 
| 99 | 99 | 
    while non_working_week_days.include?(((cwday + days - 1) % 7) + 1)  | 
| 100 | 100 | 
    days += 1  | 
| test/functional/issues_controller_test.rb (working copy) | ||
|---|---|---|
| 1799 | 1799 | 
    assert_response :success  | 
| 1800 | 1800 | 
    assert_template 'new'  | 
| 1801 | 1801 | 
    assert_select 'input[name=?]', 'issue[start_date]'  | 
| 1802 | 
          assert_select 'input[name=?][value]', 'issue[start_date]', 0
   | 
|
| 1802 | 
          assert_select 'input[name=?][value]', 'issue[start_date]', 1
   | 
|
| 1803 | 1803 | 
    end  | 
| 1804 | 1804 | 
    end  | 
| 1805 | 1805 | 
     | 
| ... | ... | |
| 2018 | 2018 | 
    assert_equal 2, issue.author_id  | 
| 2019 | 2019 | 
    assert_equal 3, issue.tracker_id  | 
| 2020 | 2020 | 
    assert_equal 2, issue.status_id  | 
| 2021 | 
        assert_equal Date.parse('2010-11-07'), issue.start_date
   | 
|
| 2021 | 
        assert_equal DateTime.parse('2010-11-07'), issue.start_date
   | 
|
| 2022 | 2022 | 
    assert_nil issue.estimated_hours  | 
| 2023 | 2023 | 
    v = issue.custom_values.where(:custom_field_id => 2).first  | 
| 2024 | 2024 | 
    assert_not_nil v  | 
| ... | ... | |
| 2085 | 2085 | 
    :id => Issue.last.id  | 
| 2086 | 2086 | 
          issue = Issue.find_by_subject('This is the test_new issue')
   | 
| 2087 | 2087 | 
    assert_not_nil issue  | 
| 2088 | 
    assert_equal Date.today, issue.start_date  | 
|
| 2088 | 
          assert_equal Date.today, issue.start_date.to_date
   | 
|
| 2089 | 2089 | 
    end  | 
| 2090 | 2090 | 
    end  | 
| 2091 | 2091 | 
     | 
| ... | ... | |
| 2260 | 2260 | 
    end  | 
| 2261 | 2261 | 
     | 
| 2262 | 2262 | 
        issue = Issue.order('id DESC').first
   | 
| 2263 | 
        assert_equal Date.parse('2012-07-14'), issue.start_date
   | 
|
| 2263 | 
        assert_equal DateTime.parse('2012-07-14'), issue.start_date
   | 
|
| 2264 | 2264 | 
    assert_nil issue.due_date  | 
| 2265 | 2265 | 
    assert_equal 'value1', issue.custom_field_value(cf1)  | 
| 2266 | 2266 | 
    assert_nil issue.custom_field_value(cf2)  | 
| ... | ... | |
| 3675 | 3675 | 
    assert_equal 2, issue.project_id, "Project is incorrect"  | 
| 3676 | 3676 | 
    assert_equal 4, issue.assigned_to_id, "Assigned to is incorrect"  | 
| 3677 | 3677 | 
    assert_equal 1, issue.status_id, "Status is incorrect"  | 
| 3678 | 
    assert_equal '2009-12-01', issue.start_date.to_s, "Start date is incorrect"  | 
|
| 3679 | 
    assert_equal '2009-12-31', issue.due_date.to_s, "Due date is incorrect"  | 
|
| 3678 | 
          assert_equal '2009-12-01 00:00:00 UTC', issue.start_date.to_s, "Start date is incorrect"
   | 
|
| 3679 | 
          assert_equal '2009-12-31 00:00:00 UTC', issue.due_date.to_s, "Due date is incorrect"
   | 
|
| 3680 | 3680 | 
    end  | 
| 3681 | 3681 | 
    end  | 
| 3682 | 3682 | 
     |