简体   繁体   中英

change date format in array elements

I have certain array elements (strings) that should be formatted as dates (mm/dd/yyyy), and they are currently causing issues when the day portion of the date is a single digit. I'm assuming the same issue will be happening with the month portion, although I've only seen it with the day portion. How would I take the elements of the cells array, and format them as dates with the format mm/dd/yyyy, with leading zeros if the month or day is a single digit.

The array will always be different, but elements 5, 6 and 7, will always need to be dates.

my array:

[1] [
    [0] "297",
    [1] "name",
    [2] "463",
    [3] "value",
    [4] "value1",
    [5] "12/8/2013",
    [6] "12/9/2013",
    [7] "12/9/2013"
],

要将您说的格式更改为mm/dd/yyyy ,请尝试以下操作:

sprintf("%02i/%02i/%4i", *(datestr.split("/").map {|i| i.to_i}))

If you want the strings converted to date objects:

require 'date'

cells = []
cells[5] = "12/8/2013"
cells[6] = "12/9/2013"
cells[7] = "12/9/2013"

(5..7).each do |i|
  cells[i] = Date.strptime(cells[i], '%m/%d/%Y')
  puts "#{cells[i]} (#{cells[i].class} object)"
end

Result:

2013-08-12 (Date object)
2013-09-12 (Date object)
2013-09-12 (Date object)

Assuming the array cells always has dates at index 5 through 7, the following will update the cells array to have the dates in mm/dd/yyyy format:

require 'date'

cells[5..7] = cells[5..7].map { |date| Date.parse(date).strftime('%m/%d/%Y') }
require 'date'

arr = ["297", "name", "463", "value", "value1", \
       "12/8/2013", "12/9/2013", "12/9/2013"]

FMT = '%m/%d/%Y'

arr.map! do |e|
  begin
    Date.strptime(e, FMT).strftime(FMT)
  rescue
    e
  end
end

arr # => ["297", "name", "463", "value", "value1", \
    #     "12/08/2013", "12/09/2013", "12/09/2013"]

I just allowed an exception to be raised by strptime when e does not represent a date with format FMT , in which case the corresponding element of arr is left unchanged. Alternatively, something like if e =~ /^\\d*\\/\\d*\\/(\\d*)$/... could be used.

One could instead use Date.parse(e).strftime(FMT) (as @OI did), because the m/d/y order is not changing, but I prefer strptime in this situation because it is more demanding of the required date format.

There could be parsing problems you're seeing that changing the format of the string won't fix at all. Consider this:

require 'date'

date = Date.parse("12/8/2013") # => #<Date: 2013-08-12 ((2456517j,0s,0n),+0s,2299161j)>
date.day # => 12

When Date tries to parse a date in this format, it assumes something that is unintuitive to Americans, but makes sense to the rest of the world. In the US, we assume a date is in mm/dd/yyyy format. The "right-thinking" people around the rest of the world understand it means dd/mm/yyyy . Ruby, being oriented toward the rest of the world uses dd/mm/yyyy .

To fix that we have to be a bit smarter about how we parse a date, and actually tell Date what to use:

date = Date.strptime("12/8/2013", '%d/%m/%Y') # => #<Date: 2013-08-12 ((2456517j,0s,0n),+0s,2299161j)>
date.day # => 12

Or:

date = Date.strptime("12/8/2013", '%m/%d/%Y') # => #<Date: 2013-12-08 ((2456635j,0s,0n),+0s,2299161j)>
date.day # => 8

If all you want to do is add zero-filled fields, you can do that several ways:

array = [
  "297",
  "name",
  "463",
  "value",
  "value1",
  "12/8/2013",
  "12/9/2013",
  "12/9/2013"
].map { |e|

  if e[%r=(\d+)/(\d+)/(\d+)=]
    '%02d/%02d/%04d' % [$1, $2, $3]
  else
    e
  end

}
array # => ["297", "name", "463", "value", "value1", "12/08/2013", "12/09/2013", "12/09/2013"]

Or using a ternary statement for more obscurity:

array = [
  "297",
  "name",
  "463",
  "value",
  "value1",
  "12/8/2013",
  "12/9/2013",
  "12/9/2013"
].map { |e|

  e[%r=(\d+)/(\d+)/(\d+)=] ? '%02d/%02d/%04d' % [$1, $2, $3] : e

}
array # => ["297", "name", "463", "value", "value1", "12/08/2013", "12/09/2013", "12/09/2013"]

If you want to reverse the fields:

array = [
  "297",
  "name",
  "463",
  "value",
  "value1",
  "12/8/2013",
  "12/9/2013",
  "12/9/2013"
].map { |e|

  if e[%r=(\d+)/(\d+)/(\d+)=]
    '%02d/%02d/%04d' % [$2, $1, $3]
  else
    e
  end

}
array # => ["297", "name", "463", "value", "value1", "08/12/2013", "09/12/2013", "09/12/2013"]

Or use the ternary line with the search results swapped.

Or use scan :

array = [
  "297",
  "name",
  "463",
  "value",
  "value1",
  "12/8/2013",
  "12/9/2013",
  "12/9/2013"
].map { |e|

  numerics = e.scan(/\d+/)
  case numerics.size
  when 3
    '%02d/%02d/%04d' % numerics
  else
    e
  end

}
array # => ["297", "name", "463", "value", "value1", "12/08/2013", "12/09/2013", "12/09/2013"]

And if you want to reverse the fields:

'%02d/%02d/%04d' % [numerics[1], numerics[0], numerics[2]]

Which to use depends on whatever you mean by "causing issues".

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM