Reputation: 45622
Is there a way to represent dates like 12/25 without year information? I'm thinking of just using an array of [month, year]
unless there is a better way.
Upvotes: 2
Views: 1651
Reputation: 4439
For anyone wondering why you would want a date without a year, here's a real-world use case. One of my projects is a contact management system and the customer wants to send notes/emails/gifts to their clients on their birthday. They usually don't get the year for their client's birthdays, so they have "June 15", "December 8", etc...
The way I handled this was not trying to force it into a date/time object, because it would technically be invalid, but just store the month/day/year as separate integer columns on the record and display them properly on the page when needed, and I make the year value optional.
Upvotes: 0
Reputation: 3454
While @Phrogz answer makes perfect sense, it has a downside:
YearlessDate = Struct.new(:month,:day)
yearless_date = YearlessDate.new(5, 8)
This interface is prone to MM, DD
versus DD, MM
confusion.
You might want to use Date
instead and consider the year 0 as "yearless date" (provided you're not a historian dealing with real dates around bc/ad of course).
The year 0 is a leap year and therefore accommodates every possible day/month duple:
Date.parse("0000-02-29").leap? #=> true
If you want to make this convention air tight, just define your own class around it, here's a minimalistic example:
class YearlessDate < Date
private :year
end
Upvotes: 0
Reputation: 3822
The most "correct" way to represent a date without a year is as a Fixnum between 001 and 365. You can do comparisons on them without having to turn it into a date, and can easily create a date for a given year as needed using Date.ordinal
Upvotes: -2
Reputation: 303168
You could use the Date class and hard set the year to a leap year (so that you could represent 2/29 if you wanted). This would be convenient if you needed to perform 'distance' calculations between two dates (assuming that you didn't need to wrap across year boundaries and that you didn't care about the off-by-one day answers you'd get when crossing 2/29 incorrectly for some years).
It might also be convenient because you could use #strftime
to display the date as (for example) "Mar-3" if you wanted.
Depending on the usage, though, I think I would probably represent them explicitly, either in a paired array or something like YearlessDate = Struct.new(:month,:day)
. That way you're not tempted to make mistakes like those mentioned above.
However, I've never had a date that wasn't actually associated with a year. Assuming this is the case for you, then @SeanHill's answer is best: keep the year info but don't display it to the user when it's not appropriate.
Upvotes: 4
Reputation: 15056
You would use the strftime function from the Time class.
time = Time.now
time.strftime("%m/%d")
Upvotes: 1