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
- #tomorrow? ⇒ 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.
- #yesterday? ⇒ Boolean
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]
159 160 161 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 159 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]
175 176 177 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 175 def datetime_array return [self.year, self.month, self.day, self.hour, self.min, self.sec] end |
#days_in_month ⇒ Object
241 242 243 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 241 def days_in_month NSCalendar.currentCalendar.rangeOfUnit(NSDayCalendarUnit, inUnit:NSMonthCalendarUnit, forDate:self).length end |
#days_in_year ⇒ Object
245 246 247 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 245 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 * 60 delta += h * 3600 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 * 3600 * 24 # 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 * 3600 * 24 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) * 3600 * 24 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) * 3600 * 24).days_in_month return_date -= delta * 3600 * 24 # same correction as above if correct_day_of_month if return_date.day < 28 return_date -= return_date.day * 3600 * 24 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) * 3600 * 24 end end end end end delta = 0 delta += d * 3600 * 24 delta += w * 3600 * 24 * 7 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 += 3600 else return_date -= 3600 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
203 204 205 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 203 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
237 238 239 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 237 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
220 221 222 223 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 220 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
151 152 153 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 151 def leap_year? self.year % 4 == 0 and self.year % 100 != 0 or self.year % 400 == 0 end |
#same_day?(other) ⇒ Boolean
138 139 140 141 142 143 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 138 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
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 183 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
229 230 231 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 229 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
211 212 213 214 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 211 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]
167 168 169 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 167 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 |
#tomorrow? ⇒ Boolean
128 129 130 131 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 128 def tomorrow? tomorrow = self.class.tomorrow return same_day?(tomorrow) 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.
147 148 149 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 147 def utc_offset return self.timezone.secondsFromGMT end |
#yesterday? ⇒ Boolean
133 134 135 136 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 133 def yesterday? yesterday = self.class.yesterday return same_day?(yesterday) end |