
1 // 2 // Copyright (c) 2006, Brian Frank and Andy Frank 3 // Licensed under the Academic Free License version 3.0 4 // 5 // History: 6 // 3 Jul 06 Brian Frank Creation 7 // 8 9 ** 10 ** DateTime represents an absolute instance in time. Fan time is 11 ** normalized as nanosecond ticks since 1 Jan 2000 UTC with a 12 ** supported range of 1901 to 2099. Fan time does not support 13 ** leap seconds (same as Java and UNIX). An instance of DateTime 14 ** also models the date and time of an absolute instance against 15 ** a specific `TimeZone`. 16 ** 17 @simple 18 const final class DateTime 19 { 20 21 ////////////////////////////////////////////////////////////////////////// 22 // Constructor 23 ////////////////////////////////////////////////////////////////////////// 24 25 ** 26 ** Return the current time using `TimeZone.current`. The tolerance 27 ** parameter specifies that you are willing to use a cached DateTime 28 ** instance as long as (now - cached <= tolerance). If tolerance is null, 29 ** then this method always creates a new DateTime instance. Using 30 ** tolerance can increase performance and save memory. The 31 ** tolerance default is 250ms. 32 ** 33 ** If you are using time to calculate relative time periods, 34 ** then use `Duration.now` instead. Duration is more efficient 35 ** and won't cause you grief when the system clock is modified. 36 ** 37 static DateTime now(Duration tolerance := 250ms) 38 39 ** 40 ** Make for nanosecond ticks since 1 Jan 2000 GMT. Throw 41 ** ArgErr if ticks represent a year out of the range 1901 42 ** to 2099. 43 ** 44 static DateTime makeTicks(Int ticks, TimeZone tz := TimeZone.current) 45 46 ** 47 ** Make for the specified date and time values: 48 ** - year: 1901-2099 49 ** - month: Month enumeration 50 ** - day: 1-31 51 ** - hour: 0-23 52 ** - min: 0-59 53 ** - sec: 0-59 54 ** - ns: 0-999_999_999 55 ** - tz: time zone used to map date/time to ns ticks 56 ** 57 ** Throw ArgErr is any of the parameters are out of range. 58 ** 59 static DateTime make(Int year, Month month, Int day, Int hour, Int min, Int sec := 0, Int ns := 0, TimeZone tz := TimeZone.current) 60 61 ** 62 ** Parse the string into a DateTime from the programmatic encoding 63 ** defined by `toStr`. If the string cannot be parsed into a valid 64 ** DateTime and checked is false then return null, otherwise throw 65 ** ParseErr. 66 ** 67 static DateTime fromStr(Str s, Bool checked := true) 68 69 ** 70 ** Private constructor. 71 ** 72 private new privateMake() 73 74 ////////////////////////////////////////////////////////////////////////// 75 // Identity 76 ////////////////////////////////////////////////////////////////////////// 77 78 ** 79 ** Two times are equal if have identical nanosecond ticks. 80 ** 81 override Bool equals(Obj that) 82 83 ** 84 ** Return nanosecond ticks for the hashcode. 85 ** 86 override Int hash() 87 88 ** 89 ** Compare based on nanosecond ticks. 90 ** 91 override Int compare(Obj obj) 92 93 ** 94 ** Return programmatic string encoding formatted as follows: 95 ** "YYYY-MM-DD'T'hh:mm:ss.FFFFFFFFFz zzzz" 96 ** 97 ** See `toLocale` for the pattern legend. The base of the 98 ** string encoding conforms to ISO 8601 and XML Schema 99 ** Part 2. The Fan format also appends the timezone name to 100 ** avoid the ambiguities associated with interpretting the time 101 ** zone offset. 102 ** 103 ** Examples: 104 ** "2000-04-03T00:00:00.123Z UTC" 105 ** "2006-10-31T01:02:03-05:00 New_York" 106 ** "2009-03-10T11:33:20Z London" 107 ** "2009-03-01T12:00:00+01:00 Amsterdam" 108 ** 109 override Str toStr() 110 111 ////////////////////////////////////////////////////////////////////////// 112 // Access 113 ////////////////////////////////////////////////////////////////////////// 114 115 ** 116 ** Return number of nanosecond ticks since 1 Jan 2000 UTC. 117 ** Dates before this epoch will return a negative integer. 118 ** 119 Int ticks() 120 121 ** 122 ** Get the year as a number such as 2007. 123 ** 124 Int year() 125 126 ** 127 ** Get the month of this date. 128 ** 129 Month month() 130 131 ** 132 ** Get the day of the month as a number between 1 and 31. 133 ** 134 Int day() 135 136 ** 137 ** Get the hour of the time as a number between 0 and 23. 138 ** 139 Int hour() 140 141 ** 142 ** Get the minutes of the time as a number between 0 and 59. 143 ** 144 Int min() 145 146 ** 147 ** Get the whole seconds of the time as a number between 0 and 59. 148 ** 149 Int sec() 150 151 ** 152 ** Get the number of nanoseconds (the fraction of seconds) as 153 ** a number between 0 and 999,999,999. 154 ** 155 Int nanoSec() 156 157 ** 158 ** Get the day of the week for this time. 159 ** 160 Weekday weekday() 161 162 ** 163 ** Get the time zone associated with this date time. 164 ** 165 TimeZone timeZone() 166 167 ** 168 ** Return if this time is within daylight savings time 169 ** for its associated time zone. 170 ** 171 Bool dst() 172 173 ** 174 ** Get the time zone's abbreviation for this time. 175 ** See `TimeZone.stdAbbr` and `TimeZone.dstAbbr`. 176 ** 177 Str timeZoneAbbr() 178 179 ** 180 ** Return the day of the year as a number between 181 ** 1 and 365 (or 1 to 366 if a leap year). 182 ** 183 Int dayOfYear() 184 185 ////////////////////////////////////////////////////////////////////////// 186 // Locale 187 ////////////////////////////////////////////////////////////////////////// 188 189 ** 190 ** Format this time according to the specified pattern. If 191 ** pattern is null, then a localized default is used. Any 192 ** ASCII letter in the pattern is interpreted as follows: 193 ** 194 ** YY Two digit year 07 195 ** YYYY Four digit year 2007 196 ** M One/two digit month 6, 11 197 ** MM Two digit month 06, 11 198 ** MMM Three letter abbr month Jun, Nov 199 ** MMMM Full month June, November 200 ** D One/two digit day 5, 28 201 ** DD Two digit day 05, 28 202 ** WWW Three letter abbr weekday Tue 203 ** WWWW Full weekday Tuesday 204 ** h One digit 24 hour (0-23) 3, 22 205 ** hh Two digit 24 hour (0-23) 03, 22 206 ** k One digit 12 hour (1-12) 3, 11 207 ** kk Two digit 12 hour (1-12) 03, 11 208 ** m One digit minutes (0-59) 4, 45 209 ** mm Two digit minutes (0-59) 04, 45 210 ** s One digit seconds (0-59) 4, 45 211 ** ss Two digit seconds (0-59) 04, 45 212 ** f* Fractional secs trailing zeros 213 ** F* Fractional secs no trailing zeros 214 ** a AM/PM marker AM, PM 215 ** z Time zone offset Z, +03:00 (ISO 8601, XML Schema) 216 ** zzz Time zone abbr EST, EDT 217 ** zzzz Time zone name New_York 218 ** 'xyz' Literal characters 219 ** 220 ** A symbol immediately preceding a "F" pattern with a no 221 ** fraction to print is skipped. 222 ** 223 Str toLocale(Str pattern := null) 224 225 ////////////////////////////////////////////////////////////////////////// 226 // Utils 227 ////////////////////////////////////////////////////////////////////////// 228 229 ** 230 ** Convert this DateTime to the specific timezone. The 231 ** absolute point time as ticks remains the same, but the 232 ** date and time fields will be converted to represent the 233 ** new time zone. 234 ** 235 DateTime toTimeZone(TimeZone tz) 236 237 ** 238 ** Return the delta between this and the given time. 239 ** 240 ** Example: 241 ** elapsed := DateTime.now - startTime 242 ** 243 Duration minus(DateTime time) 244 245 ** 246 ** Add (or subtract if duration is negative) a duration 247 ** to compute a new time. 248 ** 249 ** Example: 250 ** tomorrow := DateTime.now + 1days 251 ** yesterday := DateTime.now + -1days 252 ** 253 DateTime plus(Duration duration) 254 255 ** 256 ** Return a new DateTime with this time's nanosecond ticks truncated 257 ** according to the specified accuracy. For example 'floor(1min)' 258 ** will truncate this time to the minute such that seconds 259 ** are 0.0. This method is strictly based on absolute ticks, 260 ** it does not take into account wall-time rollovers. 261 ** 262 DateTime floor(Duration accuracy) 263 264 ** 265 ** Return if the specified year is a leap year. 266 ** 267 static Bool isLeapYear(Int year) 268 269 ** 270 ** This method computes the day of month (1-31) for a given 271 ** weekday. The pos parameter specifies the first, second, 272 ** third, or fourth occurence of the weekday. A negative pos 273 ** is used to compute the last (or second to last, etc) weekday 274 ** in the month. 275 ** 276 ** Examples: 277 ** // compute the second monday in Apr 2007 278 ** weekdayInMonth(2007, Month.apr, Weekday.mon, 2) 279 ** 280 ** // compute the last sunday in Oct 2007 281 ** weekdayInMonth(2007, Month.oct, Weekday.sun, -1) 282 ** 283 static Int weekdayInMonth(Int year, Month mon, Weekday weekday, Int pos) 284 285 ////////////////////////////////////////////////////////////////////////// 286 // HTTP 287 ////////////////////////////////////////////////////////////////////////// 288 289 ** 290 ** Parse an HTTP date according to the RFC 2616 section 3.3.1. If 291 ** invalid format and checked is false return null, otherwise 292 ** throw ParseErr. The following date formats are supported: 293 ** 294 ** Sun, 06 Nov 1994 08:49:37 GMT ; RFC 822, updated by RFC 1123 295 ** Sunday, 06-Nov-94 08:49:37 GMT ; RFC 850, obsoleted by RFC 1036 296 ** Sun Nov 6 08:49:37 1994 ; ANSI C's asctime() format 297 ** 298 static DateTime fromHttpStr(Str s, Bool checked := true) 299 300 ** 301 ** Format this time for use in an MIME or HTTP message 302 ** according to RFC 2616 using the RFC 1123 format: 303 ** 304 ** Sun, 06 Nov 1994 08:49:37 GMT 305 ** 306 Str toHttpStr() 307 308 309 }