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'], universal: [:yyyy, '-', :MM, '-', :dd, 'T', :'HH:mm:ss'], 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
- #_string_with_nsdate_format(format, timezone, locale) ⇒ Object
- #_string_with_sugarcube_format(format, timezone) ⇒ Object
- #_string_with_unicode_format(format, timezone) ⇒ Object
-
#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
12 13 14 15 16 17 18 19 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 12 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.
22 23 24 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 22 def self.now NSDate.new end |
.today ⇒ Object
26 27 28 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 26 def self.today NSDate.new.start_of_day end |
Instance Method Details
#_string_with_nsdate_format(format, timezone, locale) ⇒ Object
100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 100 def _string_with_nsdate_format(format, timezone, locale) locale_name = locale.localeIdentifier @@sugarcube_date_formatters ||= {} @@sugarcube_date_formatters[locale_name] ||= {} @@sugarcube_date_formatters[locale_name][format] ||= begin format_template = NSDateFormatter.dateFormatFromTemplate(format, options: 0, locale: locale) date_formatter = NSDateFormatter.new date_formatter.setDateFormat(format_template) date_formatter end date_formatter = @@sugarcube_date_formatters[locale_name][format] date_formatter.setTimeZone(timezone) return date_formatter.stringFromDate(self) end |
#_string_with_sugarcube_format(format, timezone) ⇒ Object
84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 84 def _string_with_sugarcube_format(format, timezone) 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 end |
#_string_with_unicode_format(format, timezone) ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 117 def _string_with_unicode_format(format, timezone) @@sugarcube_unicode_formatters ||= {} @@sugarcube_unicode_formatters[format] ||= begin date_formatter = NSDateFormatter.new date_formatter.setDateFormat(format) date_formatter end date_formatter = @@sugarcube_unicode_formatters[format] date_formatter.setTimeZone(timezone) return date_formatter.stringFromDate(self) end |
#date_array ⇒ Object
(main)> t = Time.new
=> 2012-09-27 11:29:12 +0900
(main)> t.time_array
=> [2012, 9, 27]
207 208 209 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 207 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]
223 224 225 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 223 def datetime_array return [self.year, self.month, self.day, self.hour, self.min, self.sec] end |
#days_in_month ⇒ Object
289 290 291 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 289 def days_in_month NSCalendar.currentCalendar.rangeOfUnit(NSDayCalendarUnit, inUnit:NSMonthCalendarUnit, forDate:self).length end |
#days_in_year ⇒ Object
293 294 295 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 293 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
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 146 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
251 252 253 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 251 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
285 286 287 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 285 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
268 269 270 271 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 268 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
167 168 169 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 167 def era return _calendar_components(NSEraCalendarUnit).era end |
#leap_year? ⇒ Boolean
199 200 201 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 199 def leap_year? self.year % 4 == 0 and self.year % 100 != 0 or self.year % 400 == 0 end |
#same_day?(other) ⇒ Boolean
186 187 188 189 190 191 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 186 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
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 231 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
277 278 279 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 277 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
259 260 261 262 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 259 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. If you use a Symbol, it must exist in NSDate::SugarCubeFormats.
This method accepts some options:
timezone: String or NSTimeZone. Strings get converted using NSTimeZone.timeZoneWithName unicode: if true, this method will use Unicode date format (TR35) instead of converting to a locale specific format locale: Strings or NSLocale. Strings get converted using NSLocale.localeWithLocaleIdentifier
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.
61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 61 def string_with_format(format, ={}) timezone = [:timezone] || NSTimeZone.defaultTimeZone if timezone.is_a?(NSString) timezone = NSTimeZone.timeZoneWithName(timezone) end if format.is_a?(Symbol) return _string_with_sugarcube_format(format, timezone) else unicode = [:unicode] if unicode return _string_with_unicode_format(format, timezone) else locale = [:locale] || NSLocale.currentLocale if locale.is_a?(NSString) locale = NSLocale.localeWithLocaleIdentifier(locale) end return _string_with_nsdate_format(format, timezone, locale) end end end |
#string_with_style(date_style = NSDateFormatterMediumStyle, time_style = NSDateFormatterNoStyle) ⇒ Object
38 39 40 41 42 43 44 45 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 38 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]
215 216 217 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 215 def time_array return [self.hour, self.min, self.sec] end |
#timezone ⇒ Object Also known as: timeZone
162 163 164 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 162 def timezone return _calendar_components(NSTimeZoneCalendarUnit).timeZone end |
#today? ⇒ Boolean
171 172 173 174 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 171 def today? today = self.class.new return same_day?(today) end |
#tomorrow? ⇒ Boolean
176 177 178 179 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 176 def tomorrow? tomorrow = self.class.tomorrow return same_day?(tomorrow) end |
#upto(last_date, delta = {days: 1}, &block) ⇒ Object
130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 130 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.
195 196 197 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 195 def utc_offset return self.timezone.secondsFromGMT end |
#yesterday? ⇒ Boolean
181 182 183 184 |
# File 'lib/cocoa/sugarcube-nsdate/nsdate.rb', line 181 def yesterday? yesterday = self.class.yesterday return same_day?(yesterday) end |