I want to check if a day is the last day of the month and if it is, for a function to return true, otherwise return false.
For example, if I pass in an argument of "Sun, 30 Jun 2013", the function is to return true, because it is the last day of the month, however if I pass in the argument "Mon, 03 Jun 2013" the function is to return false.
How can this be accomplished using Ruby.
If you're using Rails, you can always do this as well:
date == date.end_of_month
or to check the end of this month:
date == Date.today.end_of_month
I would do something like this
def is_last_day(mydate)
mydate.month != mydate.next_day.month
end
Parse the date with DateTime.parse. DateTime.parse has built-in support for many date formats (including those in your example), but you can always use DateTime.strptime for more complex formats.
See if the next day is 1 (first day of next month) by using Date#+.
require 'date'
def last_day?(date_string)
date = DateTime.parse(date_string)
(date + 1).day == 1
end
puts last_day?('Sun, 30 Jun 2013') # true
puts last_day?('Mon, 03 Jun 2013') # false
Related
I have a ruby script that checks a provided date, to make sure it is today's date. This is not working when the date provided doesn't have a 2 digit padding for the month. Is there anyway to get ruby to see that as equal? The example is that it says "Date Processed 3/13/2014 is not today's date 03/13/2014!" the difference is in the month - 3 vs 03. Below is the code. ev_val is provided from a csv and it is m/d/yyyy format. It is not provided with a 0 padding, though. Any thoughts?
Thanks!
tnow = Time.now
if ev_val != tnow.strftime("%m/%d/%Y")
log_linemsg = "Date Processed #{ev_val} is not today's date #{tnow.strftime("%m/%d/%Y")}! Processing date must be today's Date!!!\nSTOPPING SCRIPT!!!"
log_line = ["#{$cname}","#{log_linemsg}","","",]
puts log_linemsg
insert_logitems(connection, table_namelog, log_line)
exit
end
require "date"
date_val = Date.parse ev_val
today = Date.today
if today != date_val
log_linemsg = "Date Processed #{ev_val} is not today's date #{today}! Processing date must be today's Date!!!\nSTOPPING SCRIPT!!!"
end
Since you only care about the date portion, I would use Date instead of Time.
Take your input string and parse it into a Date object, then compare it to today's date.
?> date_val = Date.parse('3/13/2014')
=> Thu, 13 Mar 2014
>> date_val == Date.today
=> true
In your example Date.parse(ev_val) != Date.today should work for the comparison.
I have a text_field :birthday_line in my user form, that I need to parse into the user's birthday attribute.
So I'm doing something like this in my User class.
attr_accessor :birthday_line
before_save :set_birthday
def set_birthday
self.birthday = Date.strptime(birthday_line, I18n.translate("date.formats.default")
end
But the problem is that for some reason it gives me an error saying Invalid date when I try to pass in a string 27 января 1987 г. wich should be parsed to 1987-01-27.
The format and month names in my config/locales/ru.yml
ru:
date:
formats:
default: "%d %B %Y г."
month_names: [~, января, февраля, марта, апреля, мая, июня, июля, августа, сентября, октября, ноября, декабря]
seem to be correct.
Date.parse also doesn't help, it just parses the day number (27) and puts the month and year to todays date (so it'll be September 27 2013 instead of January 27 1987).
I had the same problem and what I can suggest:
string_with_cyrillic_date = '27 Января 1987'
1)create array of arrays like this
months = [["января", "Jan"], ["февраля", "Feb"], ["марта", "Mar"], ["апреля", "Apr"], ["мая", "May"], ["июня", "Jun"], ["июля", "Jul"], ["августа", "Aug"], ["сентября", "Sep"], ["октября", "Oct"], ["ноября", "Nov"], ["декабря", "Dec"]]
2) Now you can iterate this and find your cyrillic month:
months.each do |cyrillic_month, latin_month|
if string_with_cyrillic_date.match cyrillic_month
DateTime.parse string_with_cyrillic_date.gsub!(/#{cyrillic_month}/, latin_month)
end
end
And now you will receive the date that you expect
27 Jan 1987
I made new object Date.new with args (year, month). After create ruby added 01 number of day to this object by default. Is there any way to add not first day, but last day of month that i passed as arg(e.g. 28 if it will be 02month or 31 if it will be 01month) ?
use Date.civil
With Date.civil(y, m, d) or its alias .new(y, m, d), you can create a new Date object. The values for day (d) and month (m) can be negative in which case they count backwards from the end of the year and the end of the month respectively.
=> Date.civil(2010, 02, -1)
=> Sun, 28 Feb 2010
>> Date.civil(2010, -1, -5)
=> Mon, 27 Dec 2010
To get the end of the month you can also use ActiveSupport's helper end_of_month.
# Require extensions explicitly if you are not in a Rails environment
require 'active_support/core_ext'
p Time.now.utc.end_of_month # => 2013-01-31 23:59:59 UTC
p Date.today.end_of_month # => Thu, 31 Jan 2013
You can find out more on end_of_month in the Rails API Docs.
So I was searching in Google for the same thing here...
I wasn't happy with above so my solution after reading documentation
in RUBY-DOC was:
Example to get 10/31/2014
Date.new(2014,10,1).next_month.prev_day
require "date"
def find_last_day_of_month(_date)
if(_date.instance_of? String)
#end_of_the_month = Date.parse(_date.next_month.strftime("%Y-%m-01")) - 1
else if(_date.instance_of? Date)
#end_of_the_month = _date.next_month.strftime("%Y-%m-01") - 1
end
return #end_of_the_month
end
find_last_day_of_month("2018-01-01")
This is another way to find
You can do something like that:
def last_day_of_month?
(Time.zone.now.month + 1.day) > Time.zone.now.month
end
Time.zone.now.day if last_day-of_month?
This is my Time based solution. I have a personal preference to it compared to Date although the Date solutions proposed above read somehow better.
reference_time ||= Time.now
return (Time.new(reference_time.year, (reference_time.month % 12) + 1) - 1).day
btw for December you can see that year is not flipped. But this is irrelevant for the question because december always has 31 day. And for February year does not need flipping. So if you have another use case that needs year to be correct, then make sure to also change year.
Here is taking the first and third answers to find the last day of the previous month.
today_c = Date.civil(Date.today.prev_month.year, -1, -1)
p today_c
I would like to know how to get the current week number from Rails and how do I manipulate it:
Translate the week number into date.
Make an interval based on week number.
Thanks.
Use strftime:
%U - Week number of the year. The week starts with Sunday. (00..53)
%W - Week number of the year. The week starts with Monday. (00..53)
Time.now.strftime("%U").to_i # 43
# Or...
Date.today.strftime("%U").to_i # 43
If you want to add 43 weeks (or days,years,minutes, etc...) to a date, you can use 43.weeks, provided by ActiveSupport:
irb(main):001:0> 43.weeks
=> 301 days
irb(main):002:0> Date.today + 43.weeks
=> Thu, 22 Aug 2013
irb(main):003:0> Date.today + 10.days
=> Sun, 04 Nov 2012
irb(main):004:0> Date.today + 1.years # or 1.year
=> Fri, 25 Oct 2013
irb(main):005:0> Date.today + 5.months
=> Mon, 25 Mar 2013
You are going to want to stay away from strftime("%U") and "%W".
Instead, use Date.cweek.
The problem is, if you ever want to take a week number and convert it to a date, strftime won't give you a value that you can pass back to Date.commercial.
Date.commercial expects a range of values that are 1 based.
Date.strftime("%U|%W") returns a value that is 0 based. You would think you could just +1 it and it would be fine. The problem will hit you at the end of a year when there are 53 weeks. (Like what just happened...)
For example, let's look at the end of Dec 2015 and the results from your two options for getting a week number:
Date.parse("2015-12-31").strftime("%W") = 52
Date.parse("2015-12-31").cweek = 53
Now, let's look at converting that week number to a date...
Date.commercial(2015, 52, 1) = Mon, 21 Dec 2015
Date.commercial(2015, 53, 1) = Mon, 28 Dec 2015
If you blindly just +1 the value you pass to Date.commercial, you'll end up with an invalid date in other situations:
For example, December 2014:
Date.commercial(2014, 53, 1) = ArgumentError: invalid date
If you ever have to convert that week number back to a date, the only surefire way is to use Date.cweek.
date.commercial([cwyear=-4712[, cweek=1[, cwday=1[, start=Date::ITALY]]]]) → date
Creates a date object denoting the given week date.
The week and the day of week should be a negative
or a positive number (as a relative week/day from the end of year/week when negative).
They should not be zero.
For the interval
require 'date'
def week_dates( week_num )
year = Time.now.year
week_start = Date.commercial( year, week_num, 1 )
week_end = Date.commercial( year, week_num, 7 )
week_start.strftime( "%m/%d/%y" ) + ' - ' + week_end.strftime("%m/%d/%y" )
end
puts week_dates(22)
EG: Input (Week Number): 22
Output: 06/12/08 - 06/19/08
credit: Siep Korteling http://www.ruby-forum.com/topic/125140
Date#cweek seems to get the ISO-8601 week number (a Monday-based week) like %V in strftime (mentioned by #Robban in a comment).
For example, the Monday and the Sunday of the week I'm writing this:
[ Date.new(2015, 7, 13), Date.new(2015, 7, 19) ].map { |date|
date.strftime("U: %U - W: %W - V: %V - cweek: #{date.cweek}")
}
# => ["U: 28 - W: 28 - V: 29 - cweek: 29", "U: 29 - W: 28 - V: 29 - cweek: 29"]
I'm trying to figure out how to extract dates from unstructured text using Ruby.
For example, I'd like to parse the date out of this string "Applications started after 12:00 A.M. Midnight (EST) February 1, 2010 will not be considered."
Any suggestions?
Try Chronic (http://chronic.rubyforge.org/) it might be able to parse that otherwise you're going to have to use Date.strptime.
Assuming you just want dates and not datetimes:
require 'date'
string = "Applications started after 12:00 A.M. Midnight (EST) February 1, 2010 will not be considered."
r = /(January|February|March|April|May|June|July|August|September|October|November|December) (\d+{1,2}), (\d{4})/
if string[r]
date =Date.parse(string[r])
puts date
end
Also you can try a gem that can help find date in string.
Exapmle:
input = 'circa 1960 and full date 07 Jun 1941'
dates_from_string = DatesFromString.new
dates_from_string.get_structure(input)
#=> return
# [{:type=>:year, :value=>"1960", :distance=>4, :key_words=>[]},
# {:type=>:day, :value=>"07", :distance=>1, :key_words=>[]},
# {:type=>:month, :value=>"06", :distance=>1, :key_words=>[]},
# {:type=>:year, :value=>"1941", :distance=>0, :key_words=>[]}]