Class: NSDate
- Defined in:
- lib/cocoa/sugarcube-nsdate/nsdate.rb,
lib/cocoa/sugarcube-nsdate/nsdate_delta.rb
Constant Summary collapse
- SugarCubeFormats =
these formatters are used in ‘string_with_format`. Symbols are converted to a string using string_with_format’s templating, and strings are concatenated as-is
{ iso8601: [:yyyy, '-', :MM, '-', :dd, ' ', :'HH:mm:ss.SSS'], ymd: [:yyyy, '-', :MM, '-', :dd], hms: [:'HH:mm:ss.SSS'], }
Class Method Summary collapse
- .from_components(components) ⇒ Object
-
.now ⇒ Object
Time.now is defined, but not NSDate.now.
- .today ⇒ Object
- .tomorrow ⇒ Object
- .yesterday ⇒ Object
Instance Method Summary collapse
-
#date_array ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 +0900 (main)> t.time_array => [2012, 9, 27].
-
#datetime_array ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 +0900 (main)> t.time_array => [2012, 9, 12, 11, 29, 12].
- #days_in_month ⇒ Object
- #days_in_year ⇒ Object
- #delta(_components) ⇒ Object
- #downto(last_date, delta = {days: -1}, &block) ⇒ Object
-
#end_of_day ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 0900 (main)> t.end_of_day => 2012-09-28 00:00:00 0900.
-
#end_of_month ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 0900 (main)> t.end_of_month => 2012-10-01 00:00:00 0900.
-
#end_of_week(start_day = nil) ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 0900 (main)> t.start_of_week => 2012-09-30 00:00:00 0900.
- #era ⇒ Object
- #leap_year? ⇒ Boolean
- #same_day?(other) ⇒ Boolean
-
#start_of_day ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 0900 (main)> t.start_of_day => 2012-09-27 00:00:00 0900.
-
#start_of_month ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 0900 (main)> t.start_of_month => 2012-09-01 00:00:00 0900.
-
#start_of_week(start_day = nil) ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 0900 (main)> t.start_of_week => 2012-09-23 00:00:00 0900.
-
#string_with_format(format, options = {}) ⇒ Object
Pass in a format string or a Symbol.
- #string_with_style(date_style = NSDateFormatterMediumStyle, time_style = NSDateFormatterNoStyle) ⇒ Object
-
#time_array ⇒ Object
(main)> t = Time.new => 2012-09-27 11:29:12 +0900 (main)> t.time_array => [11, 29, 12].
- #timezone ⇒ Object (also: #timeZone)
- #today? ⇒ Boolean
- #upto(last_date, delta = {days: 1}, &block) ⇒ Object
-
#utc_offset ⇒ Object
In the rare case you actually get an NSDate object - not a Time object - this method is actually useful.
Class Method Details
.from_components(components) ⇒ Object
11 12 13 14 15 16 17 18 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 11 def self.from_components(components) date_components = NSDateComponents.new components.each do |property,value| date_components.send("#{property}=", value) end calendar = NSCalendar.alloc.initWithCalendarIdentifier(NSGregorianCalendar) return calendar.dateFromComponents(date_components) end |
.now ⇒ Object
Time.now is defined, but not NSDate.now.
21 22 23 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 21 def self.now NSDate.new end |
.today ⇒ Object
25 26 27 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 25 def self.today NSDate.new.start_of_day end |
Instance Method Details
#date_array ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.time_array
=> [2012, 9, 27]
149 150 151 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 149 def date_array return [self.year, self.month, self.day] end |
#datetime_array ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.time_array
=> [2012, 9, 12, 11, 29, 12]
165 166 167 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 165 def datetime_array return [self.year, self.month, self.day, self.hour, self.min, self.sec] end |
#days_in_month ⇒ Object
231 232 233 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 231 def days_in_month NSCalendar.currentCalendar.rangeOfUnit(NSDayCalendarUnit, inUnit:NSMonthCalendarUnit, forDate:self).length end |
#days_in_year ⇒ Object
235 236 237 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 235 def days_in_year leap_year? ? 366 : 365 end |
#delta(_components) ⇒ Object
3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate_delta.rb', line 3 def delta(_components) components = {}.update(_components) is_very_specific = components.has_key?(:seconds) is_very_specific ||= components.has_key?(:minutes) is_very_specific ||= components.has_key?(:hours) y = components.delete(:years) || 0 mo = components.delete(:months) || 0 d = components.delete(:days) || 0 h = components.delete(:hours) || 0 mi = components.delete(:minutes) || 0 s = components.delete(:seconds) || 0 w = components.delete(:weeks) || 0 raise "Unknown arguments #{components.keys}" unless components.empty? is_dst = self.dst? delta = s # todo: leap second adjustment? can leap seconds be detected? delta += mi.minutes delta += h.hours return_date = self + delta # using days_in_month, this is pretty easy. 12 mos per year IS a constant, # and then we just keep adding the number of days in the month (or last month # if we're going backwards). The curve ball is that when we are in day # 29,30,31, we might jump forward a month and "fall off" to the next month. # In this case, we add a correction. We will always move forwards or # backwards until the return_date.day is correct. mo += y * 12 if mo != 0 if return_date.day > 28 # we will try and preserve this day correct_day_of_month = return_date.day else correct_day_of_month = nil end if mo > 0 mo.times do delta = return_date.days_in_month return_date += delta.days # if the day_of_month is wrong, it must be because we either added PAST # the correct month (so roll back), or because we WERE rolled back and # when we moved forward a month, we were left back at the smaller day. if correct_day_of_month if return_date.day < 28 return_date -= return_date.day.days elsif return_date.day < correct_day_of_month fix = correct_day_of_month > return_date.days_in_month ? return_date.days_in_month : correct_day_of_month return_date += (fix - return_date.day).days end end end else # mo < 0 (-mo).times do # subtract *last* months number of days. # there is a REALLY rare case where subtracting return_date.day is one # hour short of "last month" and so you end up with THIS month. there # is NEVER a case when subtracting return_date.day+1 days is NOT # "previous month". dates. :-| f-em. delta = (return_date - (return_date.day+1).days).days_in_month return_date -= delta.days # same correction as above if correct_day_of_month if return_date.day < 28 return_date -= return_date.day.days elsif return_date.day < correct_day_of_month fix = correct_day_of_month > return_date.days_in_month ? return_date.days_in_month : correct_day_of_month return_date += (fix - return_date.day).days end end end end end delta = 0 delta += d.days delta += w.weeks return_date += delta # DST adjustment, unless minutes, hours, or seconds were specified. # # the thinking here is that if they WERE specified, the delta should be # accurate to that granularity. if they were omitted, the hour component # should not change, even though an off-by-one adjustment is needed # # for instance. 3/10/2012 is not in DST. 3/11/2012 IS. # Time.at(3/10/2012) # => 2012-03-10 17:00:00 -0700 # Time.at(3/10/2012).delta(days:1) # => 2012-03-11 17:00:00 -0600 # # notice the time is the SAME, even though the time zone is different. BUT: # Time.at(3/10/2012).delta(hours:24) # => 2012-03-11 17:00:00 -0600 # Time.at(3/10/2012).delta(hours:25) # => 2012-03-11 18:00:00 -0600 unless return_date.dst? == is_dst or is_very_specific if is_dst return_date += 1.hour else return_date -= 1.hour end end return return_date end |
#downto(last_date, delta = {days: -1}, &block) ⇒ Object
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 98 def downto(last_date, delta={days: -1}, &block) return if last_date > self date = self while date >= last_date if block.arity == 0 block.call else block.call(date) end new_date = date.delta(delta) break if new_date >= date date = new_date end end |
#end_of_day ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.end_of_day
=> 2012-09-28 00:00:00 +0900
193 194 195 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 193 def end_of_day return self.delta(days: 1).start_of_day end |
#end_of_month ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.end_of_month
=> 2012-10-01 00:00:00 +0900
227 228 229 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 227 def end_of_month return self.end_of_day.delta(days:days_in_month - day) end |
#end_of_week(start_day = nil) ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.start_of_week
=> 2012-09-30 00:00:00 +0900
210 211 212 213 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 210 def end_of_week(start_day=nil) result = self - days_to_week_start(start_day).days + 6.days result.end_of_day end |
#era ⇒ Object
119 120 121 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 119 def era return _calendar_components(NSEraCalendarUnit).era end |
#leap_year? ⇒ Boolean
141 142 143 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 141 def leap_year? self.year % 4 == 0 and self.year % 100 != 0 or self.year % 400 == 0 end |
#same_day?(other) ⇒ Boolean
128 129 130 131 132 133 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 128 def same_day?(other) return other.day == self.day && other.month == self.month && other.year == self.year && other.era == self.era end |
#start_of_day ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.start_of_day
=> 2012-09-27 00:00:00 +0900
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 173 def start_of_day date_components = NSDateComponents.new date_components.hour = 0 date_components.minute = 0 date_components.second = 0 date_components.day = self.day date_components.month = self.month date_components.year = self.year calendar = NSCalendar.alloc.initWithCalendarIdentifier(NSGregorianCalendar) calendar.timeZone = NSTimeZone.timeZoneForSecondsFromGMT(self.utc_offset) date = calendar.dateFromComponents(date_components) return date end |
#start_of_month ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.start_of_month
=> 2012-09-01 00:00:00 +0900
219 220 221 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 219 def start_of_month return self.start_of_day.delta(days:1 - day) end |
#start_of_week(start_day = nil) ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.start_of_week
=> 2012-09-23 00:00:00 +0900
201 202 203 204 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 201 def start_of_week(start_day=nil) result = self - days_to_week_start(start_day).days result.start_of_day end |
#string_with_format(format, options = {}) ⇒ Object
Pass in a format string or a Symbol. The Symbol must exist in NSDate::SugarCubeFormats.
See <developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1> and <www.unicode.org/reports/tr35/tr35-19.html#Date_Field_Symbol_Table> for more information about date format strings.
54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 54 def string_with_format(format, ={}) locale = [:locale] || NSLocale.currentLocale timezone = [:timezone] || NSTimeZone.defaultTimeZone if format.is_a?(Symbol) formatters = SugarCubeFormats[format] raise "No format found for #{format.inspect}" unless formatters locale = NSLocale.localeWithLocaleIdentifier "en_US" retval = '' formatters.each do |formatter| case formatter when Symbol retval << string_with_format(formatter.to_s, locale:locale, timezone:timezone) when String retval << formatter end end return retval else format_template = NSDateFormatter.dateFormatFromTemplate(format, options:0, locale:locale) date_formatter = NSDateFormatter.new date_formatter.setDateFormat(format_template) date_formatter.setTimeZone(timezone) return date_formatter.stringFromDate(self) end end |
#string_with_style(date_style = NSDateFormatterMediumStyle, time_style = NSDateFormatterNoStyle) ⇒ Object
37 38 39 40 41 42 43 44 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 37 def string_with_style(date_style=NSDateFormatterMediumStyle, time_style=NSDateFormatterNoStyle) date_formatter = NSDateFormatter.new date_style = date_style.nsdatestyle if date_style.is_a? Symbol time_style = time_style.nsdatestyle if time_style.is_a? Symbol date_formatter.setDateStyle(date_style) date_formatter.setTimeStyle(time_style) date_formatter.stringFromDate(self) end |
#time_array ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.time_array
=> [11, 29, 12]
157 158 159 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 157 def time_array return [self.hour, self.min, self.sec] end |
#timezone ⇒ Object Also known as: timeZone
114 115 116 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 114 def timezone return _calendar_components(NSTimeZoneCalendarUnit).timeZone end |
#today? ⇒ Boolean
123 124 125 126 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 123 def today? today = self.class.new return same_day?(today) end |
#upto(last_date, delta = {days: 1}, &block) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 82 def upto(last_date, delta={days: 1}, &block) return if last_date < self date = self while date <= last_date if block.arity == 0 block.call else block.call(date) end new_date = date.delta(delta) break if new_date <= date date = new_date end end |
#utc_offset ⇒ Object
In the rare case you actually get an NSDate object - not a Time object - this method is actually useful.
137 138 139 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 137 def utc_offset return self.timezone.secondsFromGMT end |