Class: NSDate
- Defined in:
- lib/sugarcube-nsdate/nsdate.rb,
lib/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) ⇒ 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/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/sugarcube-nsdate/nsdate.rb', line 21 def self.now NSDate.new end |
.today ⇒ Object
25 26 27 |
# File 'lib/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]
144 145 146 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 144 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]
160 161 162 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 160 def datetime_array return [self.year, self.month, self.day, self.hour, self.min, self.sec] end |
#days_in_month ⇒ Object
226 227 228 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 226 def days_in_month NSCalendar.currentCalendar.rangeOfUnit(NSDayCalendarUnit, inUnit:NSMonthCalendarUnit, forDate:self).length end |
#days_in_year ⇒ Object
230 231 232 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 230 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/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
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 93 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
188 189 190 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 188 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
222 223 224 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 222 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
205 206 207 208 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 205 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
114 115 116 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 114 def era return _calendar_components(NSEraCalendarUnit).era end |
#leap_year? ⇒ Boolean
136 137 138 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 136 def leap_year? self.year % 4 == 0 and self.year % 100 != 0 or self.year % 400 == 0 end |
#same_day?(other) ⇒ Boolean
123 124 125 126 127 128 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 123 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
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 168 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
214 215 216 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 214 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
196 197 198 199 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 196 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) ⇒ Object
Pass in a format string or a Symbol. The Symbol must exist in NSDate::SugarCubeFormats.
See https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/DataFormatting/Articles/dfDateFormatting10_4.html#//apple_ref/doc/uid/TP40002369-SW1 and http://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 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 54 def string_with_format(format) if format.is_a?(Symbol) formatters = SugarCubeFormats[format] raise "No format found for #{format.inspect}" unless formatters retval = '' formatters.each do |formatter| case formatter when Symbol retval << string_with_format(formatter.to_s) when String retval << formatter end end return retval else format_template = NSDateFormatter.dateFormatFromTemplate(format, options:0, locale:NSLocale.currentLocale) date_formatter = NSDateFormatter.new date_formatter.setDateFormat(format_template) 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/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]
152 153 154 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 152 def time_array return [self.hour, self.min, self.sec] end |
#timezone ⇒ Object Also known as: timeZone
109 110 111 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 109 def timezone return _calendar_components(NSTimeZoneCalendarUnit).timeZone end |
#today? ⇒ Boolean
118 119 120 121 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 118 def today? today = self.class.new return same_day?(today) end |
#upto(last_date, delta = {days: 1}, &block) ⇒ Object
77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 77 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.
132 133 134 |
# File 'lib/sugarcube-nsdate/nsdate.rb', line 132 def utc_offset return self.timezone.secondsFromGMT end |