Skip to content

Commit 722eaed

Browse files
committed
Adds support for custom date format when importing a CSV file (#950).
git-svn-id: http://svn.redmine.org/redmine/trunk@14495 e93f8b46-1217-0410-a6f0-8f06a7374b81
1 parent fe24da5 commit 722eaed

File tree

7 files changed

+59
-4
lines changed

7 files changed

+59
-4
lines changed

app/helpers/imports_helper.rb

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,4 +30,14 @@ def mapping_select_tag(import, field, options={})
3030
name = "import_settings[mapping][#{field}]"
3131
select_tag name, options_for_mapping_select(import, field, options)
3232
end
33+
34+
# Returns the options for the date_format setting
35+
def date_format_options
36+
Import::DATE_FORMATS.map do |f|
37+
format = f.gsub('%', '').gsub(/[dmY]/) do
38+
{'d' => 'DD', 'm' => 'MM', 'Y' => 'YYYY'}[$&]
39+
end
40+
[format, f]
41+
end
42+
end
3343
end

app/models/import.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,14 @@ class Import < ActiveRecord::Base
2727
validates_presence_of :filename, :user_id
2828
validates_length_of :filename, :maximum => 255
2929

30+
DATE_FORMATS = [
31+
'%Y-%m-%d',
32+
'%d/%m/%Y',
33+
'%m/%d/%Y',
34+
'%d.%m.%Y',
35+
'%d-%m-%Y'
36+
]
37+
3038
def initialize(*args)
3139
super
3240
self.settings ||= {}
@@ -201,6 +209,14 @@ def row_value(row, key)
201209
end
202210
end
203211

212+
def row_date(row, key)
213+
if s = row_value(row, key)
214+
format = settings['date_format']
215+
format = DATE_FORMATS.first unless DATE_FORMATS.include?(format)
216+
Date.strptime(s, format) rescue s
217+
end
218+
end
219+
204220
# Builds a record for the given row and returns it
205221
# To be implemented by subclasses
206222
def build_object(row)

app/models/issue_import.rb

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,18 +122,24 @@ def build_object(row)
122122
attributes['parent_issue_id'] = parent_issue_id
123123
end
124124
end
125-
if start_date = row_value(row, 'start_date')
125+
if start_date = row_date(row, 'start_date')
126126
attributes['start_date'] = start_date
127127
end
128-
if due_date = row_value(row, 'due_date')
128+
if due_date = row_date(row, 'due_date')
129129
attributes['due_date'] = due_date
130130
end
131131
if done_ratio = row_value(row, 'done_ratio')
132132
attributes['done_ratio'] = done_ratio
133133
end
134134

135135
attributes['custom_field_values'] = issue.custom_field_values.inject({}) do |h, v|
136-
if value = row_value(row, "cf_#{v.custom_field.id}")
136+
value = case v.custom_field.field_format
137+
when 'date'
138+
row_date(row, "cf_#{v.custom_field.id}")
139+
else
140+
row_value(row, "cf_#{v.custom_field.id}")
141+
end
142+
if value
137143
h[v.custom_field.id.to_s] = v.custom_field.value_from_keyword(value, issue)
138144
end
139145
h

app/views/imports/settings.html.erb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@
1717
<label><%= l(:label_encoding) %></label>
1818
<%= select_tag 'import_settings[encoding]', options_for_select(Setting::ENCODINGS, @import.settings['encoding']) %>
1919
</p>
20+
<p>
21+
<label><%= l(:setting_date_format) %></label>
22+
<%= select_tag 'import_settings[date_format]', options_for_select(date_format_options, @import.settings['date_format']) %>
23+
</p>
2024
</fieldset>
2125
<p><%= submit_tag l(:label_next).html_safe + " &#187;".html_safe, :name => nil %></p>
2226
<% end %>

test/fixtures/files/import_dates.csv

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
subject;start;due;custom
2+
Valid dates;10/07/2015;12/08/2015;14/07/2015
3+
Invalid start date;04/15/2015;;
4+
Invalid custom date;;;04/15/2015

test/functional/imports_controller_test.rb

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,13 +69,14 @@ def test_post_settings_should_update_settings
6969
import = generate_import
7070

7171
post :settings, :id => import.to_param,
72-
:import_settings => {:separator => ":", :wrapper => "|", :encoding => "UTF-8"}
72+
:import_settings => {:separator => ":", :wrapper => "|", :encoding => "UTF-8", :date_format => '%m/%d/%Y'}
7373
assert_redirected_to "/imports/#{import.to_param}/mapping"
7474

7575
import.reload
7676
assert_equal ":", import.settings['separator']
7777
assert_equal "|", import.settings['wrapper']
7878
assert_equal "UTF-8", import.settings['encoding']
79+
assert_equal '%m/%d/%Y', import.settings['date_format']
7980
end
8081

8182
def test_post_settings_should_update_total_items_count

test/unit/issue_import_test.rb

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,20 @@ def test_is_private_should_be_set_based_on_user_locale
7878
assert_equal [false, true, false], issues.map(&:is_private)
7979
end
8080

81+
def test_dates_should_be_parsed_using_date_format_setting
82+
field = IssueCustomField.generate!(:field_format => 'date', :is_for_all => true, :trackers => Tracker.all)
83+
import = generate_import_with_mapping('import_dates.csv')
84+
import.settings.merge!('date_format' => Import::DATE_FORMATS[1])
85+
import.mapping.merge!('subject' => '0', 'start_date' => '1', 'due_date' => '2', "cf_#{field.id}" => '3')
86+
import.save!
87+
88+
issue = new_record(Issue) { import.run } # only 1 valid issue
89+
assert_equal "Valid dates", issue.subject
90+
assert_equal Date.parse('2015-07-10'), issue.start_date
91+
assert_equal Date.parse('2015-08-12'), issue.due_date
92+
assert_equal '2015-07-14', issue.custom_field_value(field)
93+
end
94+
8195
def test_run_should_remove_the_file
8296
import = generate_import_with_mapping
8397
file_path = import.filepath

0 commit comments

Comments
 (0)