How to correctly swap some characters in string - ruby

I have a string that represents a date:
"12.27.1995"
I need to swap the month and the day to get:
"27.12.1995"
I did:
date = "12.27.1995"
month = date[0]+date[1]
day = date[3]+date[4]
date[0] = day[0]
date[1] = day[1]
date[3] = month[0]
date[4] = month[1]
It works good, but looks to bad for me. Is it possible to make it more reliable using less code?

Since your string represents a date, you might want to use a Date object, with strptime to parse the original string and strftime to output it in the desired format:
require 'date'
date = Date.strptime("12.27.1995", "%m.%d.%Y")
puts date.strftime("%d.%m.%Y")
# 27.12.1995

Yes. Perhaps like this:
date = "12.27.1995"
m, d, y = date.split(".")
date = [d, m, y].join(".")

While the answer by #sawa is perfectly valid and should be used here, I would show some technic which is wrong and should not be used here, but might be helpful for anybody to swap two fixed parts of the string:
"12.27.1995".tap { |s| s[0..1], s[3..4] = s[3..4], s[0..1] }
#⇒ "27.12.1995"

Not elegant, but a way using regex captures:
/(\d{1,2})\.(\d{1,2})\.(\d{4})/.match "12.27.1995"
[$2, $1, $3].join('.') #=> "27.12.1995"

Related

Creating an array of something by not today's date?

I have two arrays I'm trying to make. The first one is all the "quotes" with a "follow_up_date" that is today's date. My code looks like:
#dailyTasks = Quote.where(:follow_up => 1,:follow_up_date => Date.today())
This works perfectly for me and is not the issue.
My next array is the same concept but all the quotes to be added are quotes with a follow_up_date that is not today's date. Something like this is what I'm looking for:
#upcomingTasks = Quote.where(:follow_up => 1, :follow_up_date => NOT Date.today())
Does anyone know the proper syntax I should be using to add quotes whose date is NOT today's date?
You can use where.not to get that negation:
#upcomingTasks = Quote.where(follow_up: 1).where.not(follow_up_date: Date.today())
You can simply use equality operators
today = Date.today
today == some_other_date
Can also use < and > to check if date is earlier or later than another.
today < some_other_date
If using Date.today, it does not compare the exact time like it would if using Time.now from other time/date related built-ins.

Incrementing numeric parameter in a URL parameter string?

I've had a look round and can't find what I need on Stack Overflow, and was wondering if someone had a simple solution.
I want to find a parameter within a URL and increment its value, so, as an example:
?kws=&pstc=&cty=&prvnm=1
I want to be able to locate the prvnm parameter no matter where it is in the string and increment its value by 1.
I know I could split the parameters into an array, find the key, increment it and write it back but that seems rather long winded and wondered if someone else had any ideas!
require "uri"
url = "http://example.com/?kws=&pstc=&cty=&prvnm=1"
def new_url(url)
uri = URI.parse(url)
hsh = Hash[URI.decode_www_form(uri.query)]
hsh['prvnm'] = hsh['prvnm'].next
uri.query = URI.encode_www_form(hsh).to_s
uri.to_s
end
new_url(url) # => "http://example.com/?kws=&pstc=&cty=&prvnm=2"
There are already four answers, so I had to come up with something a little different:
s = "?kws=&pstc=&cty=&prvnm=1"
head, sep, tail = s.partition(/(?<=[?&]prvnm=)\d+/)
head + (sep.to_i + 1).to_s + tail # => "?kws=&pstc=&cty=&prvnm=2"
'String#partition' returns an array of three strings [head, sep, tail], such that head + sep + tail => s, where separator is partition's argument, which can be a string or a regex.
We want the separator to be the digits following &prvnm=. We therefore use a regex with \d+ preceeded by the aforementioned string which we want to treat as having zero length, so it will not be included in the separator. That calls for a "positive look-behind": (?<=&prvnm=). \d+ is "greedy", so it take all consequetive digits.
For the given value of s, head, sep, tail = s.partition(/(?<=&prvnm=)(\d+)/)
=> ["?kws=&pstc=&cty=&prvnm=", "1", ""].
Edit: my thanks to #quetzalcoatl for pointing out that I needed to change (?<=&prvnm=) in my regex to what I have now, as what I had would fail when ?prvnm= was at the beginning of the string.
split the string by `&`
then iterate over the parts
then split each part by `=` and inspect the results
when found `prvnm`, parse the integer and increment it
then join the bits by '='
then join the parts by '&'
Or, use regex like:
/[?&]prvnm=\d+/
and parse the result and then do a replacement.
Or, get some URL-parsing library..
Try something like this:
params = "?kws=&pstc=&cty=&prvnm=1"
num = params.scan(/prvnm=(\d)/)[0].join.to_i
puts num + 1
Use:
require 'uri'
Then:
parsed-url= URI.parse( ur full url)
r = CGI.parse(parsed_url.query)
r is now a hash of all your query parameters.
You can easily access it by using:
r["prsvn"].to_i + 1

Change string in a date format to another format

I have a string like this (YYYYMMDD):
20120225
And I want to have a string like this (MM/DD/YYYY):
02/25/2012
What's a good way of doing this in Ruby? I have thought about converting the first string to a Date, and then change the format. Or just treating the string and getting the parts I want and build the new string.
Parsing it then formatting it is the best solution:
Date.parse("20120225").strftime("%m/%d/%Y") #=> "02/25/2012"
strptime parses the string representation of date with the specified template and creates a date object.
Date.strptime('20120225', '%Y%m%d').strftime("%m/%d/%Y") #=> "02/25/2012"
Just for fun how about:
'20120225'.unpack('A4A2A2').rotate.join('/')
It's possible with regular expressions:
s1 = '20120225'
s2 = "$2/$3/$1" if s1 =~ /(\d{4})(\d{2})(\d{2})/
Or if you're sure of the format of your string and have performance issues, I think the best solution is
s2 = s1[4..5] + '/' + s1[6..7] + '/' + s1[0..3]
But if you have no performance needs, I think the solution of Andrew Marshall is better because it checks the date validity.

Ruby Date.strptime difficulties when parsing 13/Nov/11

When parsing a Jira Custom Field containing a date (e.g. 13/Nov/11) I started with this:
elsif custom.customfieldId == "customfield_10282"
#agenda_item.planned_release_date = custom.values.to_s
But the database stores it as 11/13/0011. So I got clever and used this:
elsif custom.customfieldId == "customfield_10282"
#agenda_item.planned_release_date = Date.strptime(custom.values, "%d/%m/%Y")
And now I get:
private method sub!' called for ["15/Nov/11"]:Jira4R::V2::ArrayOf_xsd_string
C:/Ruby187/lib/ruby/1.8/date/format.rb:429:in_strptime_i'
C:/Ruby187/lib/ruby/1.8/date/format.rb:401:in scan'
C:/Ruby187/lib/ruby/1.8/date/format.rb:401:in_strptime_i'
C:/Ruby187/lib/ruby/1.8/date/format.rb:601:in `_strptime'
[truncated the rest of the stack]
What am I missing?
This works:
p Date.strptime('13/Nov/11', "%d/%b/%y")
Your problems:
`%Y is the year with 4 digits (2011). Use %y
%m is the month in digits (11). Use %b instead (Nov)
If I properly understand your issue, try to use this:
Date.strptime('13/Nov/11', "%d/%b/%y") # => 2011-11-13
You have abbreviated month name and there for you should use b format directive. Beside this because your year contains only two last numbers, use y directive.

What is the best way to get 51, out of the following string

What is the best way to get '51', out of the following string in ruby :
"<https://api.example.com/users/lgs/api?page=2>; rel=\"next\", <https://api.example.com/users/lgs/api?page=51>; rel=\"last\""
Thanks in advance
Luca
If you know there're only two numbers in that string then this is enough:
str = '"<https://api.example.com/users/lgs/api?page=2>; rel=\"next\", <https://api.example.com/users/lgs/api?page=51>; rel=\"last\""'
p str.scan(/\d+/).last #=> "51"
If not then provide more detail to make the regex more precise. Also you can add to_i if you need the answer as a number.
You can use regexp in this way:
res = str.match /.page=(\d+)./
in this way you are "capturing all the digits between "(" and ")" (in the last token), and you result will be store in
res.captures.first
(or simply in $1 variable)

Resources