rasputin 0.5.1 → 0.5.2

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore CHANGED
@@ -1,4 +1,3 @@
1
1
  *.gem
2
2
  .bundle
3
- Gemfile.lock
4
3
  pkg/*
data/Gemfile.lock ADDED
@@ -0,0 +1,67 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ rasputin (0.2.0)
5
+ actionpack (~> 3.1.0.rc4)
6
+ railties (~> 3.1.0.rc4)
7
+ sprockets (>= 2.0.0.beta.10)
8
+
9
+ GEM
10
+ remote: http://rubygems.org/
11
+ specs:
12
+ actionpack (3.1.0.rc4)
13
+ activemodel (= 3.1.0.rc4)
14
+ activesupport (= 3.1.0.rc4)
15
+ builder (~> 3.0.0)
16
+ erubis (~> 2.7.0)
17
+ i18n (~> 0.6)
18
+ rack (~> 1.3.0)
19
+ rack-cache (~> 1.0.1)
20
+ rack-mount (~> 0.8.1)
21
+ rack-test (~> 0.6.0)
22
+ sprockets (~> 2.0.0.beta.10)
23
+ tzinfo (~> 0.3.27)
24
+ activemodel (3.1.0.rc4)
25
+ activesupport (= 3.1.0.rc4)
26
+ bcrypt-ruby (~> 2.1.4)
27
+ builder (~> 3.0.0)
28
+ i18n (~> 0.6)
29
+ activesupport (3.1.0.rc4)
30
+ multi_json (~> 1.0)
31
+ bcrypt-ruby (2.1.4)
32
+ builder (3.0.0)
33
+ erubis (2.7.0)
34
+ hike (1.1.0)
35
+ i18n (0.6.0)
36
+ multi_json (1.0.3)
37
+ rack (1.3.0)
38
+ rack-cache (1.0.2)
39
+ rack (>= 0.4)
40
+ rack-mount (0.8.1)
41
+ rack (>= 1.0.0)
42
+ rack-ssl (1.3.2)
43
+ rack
44
+ rack-test (0.6.0)
45
+ rack (>= 1.0)
46
+ railties (3.1.0.rc4)
47
+ actionpack (= 3.1.0.rc4)
48
+ activesupport (= 3.1.0.rc4)
49
+ rack-ssl (~> 1.3.2)
50
+ rake (>= 0.8.7)
51
+ rdoc (~> 3.4)
52
+ thor (~> 0.14.6)
53
+ rake (0.9.2)
54
+ rdoc (3.8)
55
+ sprockets (2.0.0.beta.10)
56
+ hike (~> 1.0)
57
+ rack (~> 1.0)
58
+ tilt (!= 1.3.0, ~> 1.1)
59
+ thor (0.14.6)
60
+ tilt (1.3.2)
61
+ tzinfo (0.3.29)
62
+
63
+ PLATFORMS
64
+ ruby
65
+
66
+ DEPENDENCIES
67
+ rasputin!
data/README.md CHANGED
@@ -8,15 +8,17 @@ It provide direct requires for official sproutcore packages :
8
8
  * sproutcore
9
9
  * sproutcore-datastore
10
10
  * sproutcore-statechart
11
- * sproutcore-ui
12
11
 
13
12
  And it also provides some unnoficial packages :
14
13
 
15
14
  * sproutcore-ajax (backport form sc 1.x API but using jQuery $.ajax)
16
- * sproutcore-debug (backport form sc 1.x Logger)
17
- * sproutcore-string (useful String methods, borrowed from underscore string)
18
- * sproutcore-ui (jQuery UI wrappers for sc 2.0)
19
- * sproutcore-throbber (jQuery UI throbber and it wrapper for JUI)
15
+ * sproutcore-jui (jQuery UI wrappers for sc 2.0)
16
+ * sproutcore-throbber (jQuery UI throbber and it's wrapper for JUI)
20
17
 
21
18
  Rasputin also provide sprockets engine for handlebars templates. Any template in your
22
19
  javascript assets folder with extention handlebars will be availabel in sproutcore.
20
+
21
+ Examples :
22
+
23
+ todos/templates/item.handlebars >> SC.TEMPLATES['todos_item']
24
+ todos/ui/templates/stats.handlebars >> SC.TEMPLATES['todos_ui_stats']
@@ -1,3 +1,3 @@
1
1
  module Rasputin
2
- VERSION = "0.5.1"
2
+ VERSION = "0.5.2"
3
3
  end
@@ -275,7 +275,7 @@ SC.Response = SC.Object.extend(
275
275
  */
276
276
  toString: function() {
277
277
  var ret = this._super();
278
- return "%@<%@ %@, status=%@".fmt(ret, this.get('type'), this.get('address'), this.get('status'));
278
+ return "%@<%@ %@, status=%@".fmt(ret, this.get('type'), this.get('url'), this.get('status'));
279
279
  },
280
280
 
281
281
  /**
@@ -329,7 +329,7 @@ SC.XHRResponse = SC.Response.extend({
329
329
  key, value;
330
330
  if (idx>=0) {
331
331
  key = header.slice(0,idx);
332
- value = SC.String.trim(header.slice(idx+1));
332
+ value = header.slice(idx+1).trim();
333
333
  ret[key] = value ;
334
334
  }
335
335
  }, this);
@@ -1251,6 +1251,1176 @@ SC.IndexSet.reopenClass({
1251
1251
  // License: Licensed under MIT license (see license.js)
1252
1252
  // ==========================================================================
1253
1253
 
1254
+ var get = SC.get, set = SC.set;
1255
+
1256
+ // simple copy op needed for just this code.
1257
+ function copy(opts) {
1258
+ var ret = {};
1259
+ for(var key in opts) {
1260
+ if (opts.hasOwnProperty(key)) ret[key] = opts[key];
1261
+ }
1262
+ return ret;
1263
+ }
1264
+
1265
+ /**
1266
+ Standard error thrown by `SC.Scanner` when it runs out of bounds
1267
+
1268
+ @static
1269
+ @constant
1270
+ @type Error
1271
+ */
1272
+ SC.SCANNER_OUT_OF_BOUNDS_ERROR = "Out of bounds.";
1273
+
1274
+ /**
1275
+ Standard error thrown by `SC.Scanner` when you pass a value not an integer.
1276
+
1277
+ @static
1278
+ @constant
1279
+ @type Error
1280
+ */
1281
+ SC.SCANNER_INT_ERROR = "Not an int.";
1282
+
1283
+ /**
1284
+ Standard error thrown by `SC.Scanner` when it cannot find a string to skip.
1285
+
1286
+ @static
1287
+ @constant
1288
+ @type Error
1289
+ */
1290
+ SC.SCANNER_SKIP_ERROR = "Did not find the string to skip.";
1291
+
1292
+ /**
1293
+ Standard error thrown by `SC.Scanner` when it can any kind a string in the
1294
+ matching array.
1295
+
1296
+ @static
1297
+ @constant
1298
+ @type Error
1299
+ */
1300
+ SC.SCANNER_SCAN_ARRAY_ERROR = "Did not find any string of the given array to scan.";
1301
+
1302
+ /**
1303
+ Standard error thrown when trying to compare two dates in different
1304
+ timezones.
1305
+
1306
+ @static
1307
+ @constant
1308
+ @type Error
1309
+ */
1310
+ SC.DATETIME_COMPAREDATE_TIMEZONE_ERROR = "Can't compare the dates of two DateTimes that don't have the same timezone.";
1311
+
1312
+ /**
1313
+ Standard ISO8601 date format
1314
+
1315
+ @static
1316
+ @type String
1317
+ @default '%Y-%m-%dT%H:%M:%S%Z'
1318
+ @constant
1319
+ */
1320
+ SC.DATETIME_ISO8601 = '%Y-%m-%dT%H:%M:%S%Z';
1321
+
1322
+
1323
+ /**
1324
+ @ignore
1325
+ @private
1326
+
1327
+ A Scanner reads a string and interprets the characters into numbers. You
1328
+ assign the scanner's string on initialization and the scanner progresses
1329
+ through the characters of that string from beginning to end as you request
1330
+ items.
1331
+
1332
+ Scanners are used by `DateTime` to convert strings into `DateTime` objects.
1333
+
1334
+ @extends SC.Object
1335
+ @since SproutCore 1.0
1336
+ @author Martin Ottenwaelter
1337
+ */
1338
+ var Scanner = SC.Object.extend({
1339
+
1340
+ /**
1341
+ The string to scan. You usually pass it to the create method:
1342
+
1343
+ Scanner.create({string: 'May, 8th'});
1344
+
1345
+ @type String
1346
+ */
1347
+ string: null,
1348
+
1349
+ /**
1350
+ The current scan location. It is incremented by the scanner as the
1351
+ characters are processed.
1352
+ The default is 0: the beginning of the string.
1353
+
1354
+ @type Integer
1355
+ */
1356
+ scanLocation: 0,
1357
+
1358
+ /**
1359
+ Reads some characters from the string, and increments the scan location
1360
+ accordingly.
1361
+
1362
+ @param {Integer} len The amount of characters to read
1363
+ @throws {SC.SCANNER_OUT_OF_BOUNDS_ERROR} If asked to read too many characters
1364
+ @returns {String} The characters
1365
+ */
1366
+ scan: function(len) {
1367
+ if (this.scanLocation + len > this.length) {
1368
+ throw new Error(SC.SCANNER_OUT_OF_BOUNDS_ERROR);
1369
+ }
1370
+ var str = this.string.substr(this.scanLocation, len);
1371
+ this.scanLocation += len;
1372
+ return str;
1373
+ },
1374
+
1375
+ /**
1376
+ Reads some characters from the string and interprets it as an integer.
1377
+
1378
+ @param {Integer} min_len The minimum amount of characters to read
1379
+ @param {Integer} [max_len] The maximum amount of characters to read (defaults to the minimum)
1380
+ @throws {SC.SCANNER_INT_ERROR} If asked to read non numeric characters
1381
+ @returns {Integer} The scanned integer
1382
+ */
1383
+ scanInt: function(min_len, max_len) {
1384
+ if (max_len === undefined) max_len = min_len;
1385
+ var str = this.scan(max_len);
1386
+ var re = new RegExp("^\\d{" + min_len + "," + max_len + "}");
1387
+ var match = str.match(re);
1388
+ if (!match) throw new Error(SC.SCANNER_INT_ERROR);
1389
+ if (match[0].length < max_len) {
1390
+ this.scanLocation += match[0].length - max_len;
1391
+ }
1392
+ return parseInt(match[0], 10);
1393
+ },
1394
+
1395
+ /**
1396
+ Attempts to skip a given string.
1397
+
1398
+ @param {String} str The string to skip
1399
+ @throws {SC.SCANNER_SKIP_ERROR} If the given string could not be scanned
1400
+ @returns {Boolean} YES if the given string was successfully scanned, NO otherwise
1401
+ */
1402
+ skipString: function(str) {
1403
+ if (this.scan(str.length) !== str) {
1404
+ throw new Error(SC.SCANNER_SKIP_ERROR);
1405
+ }
1406
+
1407
+ return YES;
1408
+ },
1409
+
1410
+ /**
1411
+ Attempts to scan any string in a given array.
1412
+
1413
+ @param {Array} ary the array of strings to scan
1414
+ @throws {SC.SCANNER_SCAN_ARRAY_ERROR} If no string of the given array is found
1415
+ @returns {Integer} The index of the scanned string of the given array
1416
+ */
1417
+ scanArray: function(ary) {
1418
+ for (var i = 0, len = ary.length; i < len; i++) {
1419
+ if (this.scan(ary[i].length) === ary[i]) {
1420
+ return i;
1421
+ }
1422
+ this.scanLocation -= ary[i].length;
1423
+ }
1424
+ throw new Error(SC.SCANNER_SCAN_ARRAY_ERROR);
1425
+ }
1426
+
1427
+ });
1428
+
1429
+
1430
+ /** @class
1431
+
1432
+ A class representation of a date and time. It's basically a wrapper around
1433
+ the Date javascript object, KVO-friendly and with common date/time
1434
+ manipulation methods.
1435
+
1436
+ This object differs from the standard JS Date object, however, in that it
1437
+ supports time zones other than UTC and that local to the machine on which
1438
+ it is running. Any time zone can be specified when creating an
1439
+ `SC.DateTime` object, e.g.
1440
+
1441
+ // Creates a DateTime representing 5am in Washington, DC and 10am in
1442
+ // London
1443
+ var d = SC.DateTime.create({ hour: 5, timezone: 300 }); // -5 hours from UTC
1444
+ var e = SC.DateTime.create({ hour: 10, timezone: 0 }); // same time, specified in UTC
1445
+
1446
+ and it is true that `d.isEqual(e)`.
1447
+
1448
+ The time zone specified upon creation is permanent, and any calls to
1449
+ `get()` on that instance will return values expressed in that time zone. So,
1450
+
1451
+ d.hour returns 5.
1452
+ e.hour returns 10.
1453
+
1454
+ but
1455
+
1456
+ d.milliseconds === e.milliseconds
1457
+
1458
+ is true, since they are technically the same position in time.
1459
+
1460
+ @extends SC.Object
1461
+ @extends SC.Freezable
1462
+ @extends SC.Copyable
1463
+ @author Martin Ottenwaelter
1464
+ @author Jonathan Lewis
1465
+ @author Josh Holt
1466
+ @since SproutCore 1.0
1467
+ */
1468
+ SC.DateTime = SC.Object.extend(SC.Freezable, SC.Copyable,
1469
+ /** @scope SC.DateTime.prototype */ {
1470
+
1471
+ /**
1472
+ @private
1473
+
1474
+ Internal representation of a date: the number of milliseconds
1475
+ since January, 1st 1970 00:00:00.0 UTC.
1476
+
1477
+ @property
1478
+ @type {Integer}
1479
+ */
1480
+ _ms: 0,
1481
+
1482
+ /** @read-only
1483
+ The offset, in minutes, between UTC and the object's timezone.
1484
+ All calls to `get()` will use this time zone to translate date/time
1485
+ values into the zone specified here.
1486
+
1487
+ @type Integer
1488
+ */
1489
+ timezone: 0,
1490
+
1491
+ /**
1492
+ A `SC.DateTime` instance is frozen by default for better performance.
1493
+
1494
+ @type Boolean
1495
+ */
1496
+ isFrozen: YES,
1497
+
1498
+ /**
1499
+ Returns a new `SC.DateTime` object where one or more of the elements have
1500
+ been changed according to the options parameter. The time options (hour,
1501
+ minute, sec, usec) reset cascadingly, so if only the hour is passed, then
1502
+ minute, sec, and usec is set to 0. If the hour and minute is passed, then
1503
+ sec and usec is set to 0.
1504
+
1505
+ If a time zone is passed in the options hash, all dates and times are
1506
+ assumed to be local to it, and the returned `SC.DateTime` instance has
1507
+ that time zone. If none is passed, it defaults to `SC.DateTime.timezone`.
1508
+
1509
+ Note that passing only a time zone does not affect the actual milliseconds
1510
+ since Jan 1, 1970, only the time zone in which it is expressed when
1511
+ displayed.
1512
+
1513
+ @see SC.DateTime#create for the list of options you can pass
1514
+ @returns {SC.DateTime} copy of receiver
1515
+ */
1516
+ adjust: function(options, resetCascadingly) {
1517
+ var timezone;
1518
+
1519
+ options = options ? copy(options) : {};
1520
+ timezone = (options.timezone !== undefined) ? options.timezone : (this.timezone !== undefined) ? this.timezone : 0;
1521
+
1522
+ return this.constructor._adjust(options, this._ms, timezone, resetCascadingly)._createFromCurrentState();
1523
+ },
1524
+
1525
+ /**
1526
+ Returns a new `SC.DateTime` object advanced according the the given
1527
+ parameters. Don't use floating point values, it might give unpredicatble results.
1528
+
1529
+ @see SC.DateTime#create for the list of options you can pass
1530
+ @param {Hash} options the amount of date/time to advance the receiver
1531
+ @returns {DateTime} copy of the receiver
1532
+ */
1533
+ advance: function(options) {
1534
+ return this.constructor._advance(options, this._ms, this.timezone)._createFromCurrentState();
1535
+ },
1536
+
1537
+ /**
1538
+ Generic getter.
1539
+
1540
+ The properties you can get are:
1541
+ - `year`
1542
+ - `month` (January is 1, contrary to JavaScript Dates for which January is 0)
1543
+ - `day`
1544
+ - `dayOfWeek` (Sunday is 0)
1545
+ - `hour`
1546
+ - `minute`
1547
+ - `second`
1548
+ - `millisecond`
1549
+ - `milliseconds`, the number of milliseconds since
1550
+ January, 1st 1970 00:00:00.0 UTC
1551
+ - `isLeapYear`, a boolean value indicating whether the receiver's year
1552
+ is a leap year
1553
+ - `daysInMonth`, the number of days of the receiver's current month
1554
+ - `dayOfYear`, January 1st is 1, December 31th is 365 for a common year
1555
+ - `week` or `week1`, the week number of the current year, starting with
1556
+ the first Sunday as the first day of the first week (00..53)
1557
+ - `week0`, the week number of the current year, starting with
1558
+ the first Monday as the first day of the first week (00..53)
1559
+ - `lastMonday`, `lastTuesday`, etc., `nextMonday`,
1560
+ `nextTuesday`, etc., the date of the last or next weekday in
1561
+ comparison to the receiver.
1562
+
1563
+ @param {String} key the property name to get
1564
+ @return the value asked for
1565
+ */
1566
+ unknownProperty: function(key) {
1567
+ return this.constructor._get(key, this._ms, this.timezone);
1568
+ },
1569
+
1570
+ /**
1571
+ Formats the receiver according to the given format string. Should behave
1572
+ like the C strftime function.
1573
+
1574
+ The format parameter can contain the following characters:
1575
+ - %a -- The abbreviated weekday name (``Sun'')
1576
+ - %A -- The full weekday name (``Sunday'')
1577
+ - %b -- The abbreviated month name (``Jan'')
1578
+ - %B -- The full month name (``January'')
1579
+ - %c -- The preferred local date and time representation
1580
+ - %d -- Day of the month (01..31)
1581
+ - %D -- Day of the month (0..31)
1582
+ - %h -- Hour of the day, 24-hour clock (0..23)
1583
+ - %H -- Hour of the day, 24-hour clock (00..23)
1584
+ - %i -- Hour of the day, 12-hour clock (1..12)
1585
+ - %I -- Hour of the day, 12-hour clock (01..12)
1586
+ - %j -- Day of the year (001..366)
1587
+ - %m -- Month of the year (01..12)
1588
+ - %M -- Minute of the hour (00..59)
1589
+ - %p -- Meridian indicator (``AM'' or ``PM'')
1590
+ - %S -- Second of the minute (00..60)
1591
+ - %s -- Milliseconds of the second (000..999)
1592
+ - %U -- Week number of the current year,
1593
+ starting with the first Sunday as the first
1594
+ day of the first week (00..53)
1595
+ - %W -- Week number of the current year,
1596
+ starting with the first Monday as the first
1597
+ day of the first week (00..53)
1598
+ - %w -- Day of the week (Sunday is 0, 0..6)
1599
+ - %x -- Preferred representation for the date alone, no time
1600
+ - %X -- Preferred representation for the time alone, no date
1601
+ - %y -- Year without a century (00..99)
1602
+ - %Y -- Year with century
1603
+ - %Z -- Time zone (ISO 8601 formatted)
1604
+ - %% -- Literal ``%'' character
1605
+
1606
+ @param {String} format the format string
1607
+ @return {String} the formatted string
1608
+ */
1609
+ toFormattedString: function(fmt) {
1610
+ return this.constructor._toFormattedString(fmt, this._ms, this.timezone);
1611
+ },
1612
+
1613
+ /**
1614
+ Formats the receiver according ISO 8601 standard. It is equivalent to
1615
+ calling toFormattedString with the `'%Y-%m-%dT%H:%M:%S%Z'` format string.
1616
+
1617
+ @return {String} the formatted string
1618
+ */
1619
+ toISO8601: function(){
1620
+ return this.constructor._toFormattedString(SC.DATETIME_ISO8601, this._ms, this.timezone);
1621
+ },
1622
+
1623
+ /**
1624
+ @private
1625
+
1626
+ Creates a string representation of the receiver.
1627
+
1628
+ (Debuggers often call the `toString` method. Because of the way
1629
+ `SC.DateTime` is designed, calling `SC.DateTime._toFormattedString` would
1630
+ have a nasty side effect. We shouldn't therefore call any of
1631
+ `SC.DateTime`'s methods from `toString`)
1632
+
1633
+ @returns {String}
1634
+ */
1635
+ toString: function() {
1636
+ return "UTC: " +
1637
+ new Date(this._ms).toUTCString() +
1638
+ ", timezone: " +
1639
+ this.timezone;
1640
+ },
1641
+
1642
+ /**
1643
+ Returns `YES` if the passed `SC.DateTime` is equal to the receiver, ie: if their
1644
+ number of milliseconds since January, 1st 1970 00:00:00.0 UTC are equal.
1645
+ This is the preferred method for testing equality.
1646
+
1647
+ @see SC.DateTime#compare
1648
+ @param {SC.DateTime} aDateTime the DateTime to compare to
1649
+ @returns {Boolean}
1650
+ */
1651
+ isEqual: function(aDateTime) {
1652
+ return SC.DateTime.compare(this, aDateTime) === 0;
1653
+ },
1654
+
1655
+ /**
1656
+ Returns a copy of the receiver. Because of the way `SC.DateTime` is designed,
1657
+ it just returns the receiver.
1658
+
1659
+ @returns {SC.DateTime}
1660
+ */
1661
+ copy: function() {
1662
+ return this;
1663
+ },
1664
+
1665
+ /**
1666
+ Returns a copy of the receiver with the timezone set to the passed
1667
+ timezone. The returned value is equal to the receiver (ie `SC.Compare`
1668
+ returns 0), it is just the timezone representation that changes.
1669
+
1670
+ If you don't pass any argument, the target timezone is assumed to be 0,
1671
+ ie UTC.
1672
+
1673
+ Note that this method does not change the underlying position in time,
1674
+ but only the time zone in which it is displayed. In other words, the underlying
1675
+ number of milliseconds since Jan 1, 1970 does not change.
1676
+
1677
+ @return {SC.DateTime}
1678
+ */
1679
+ toTimezone: function(timezone) {
1680
+ if (timezone === undefined) timezone = 0;
1681
+ return this.advance({ timezone: timezone - this.timezone });
1682
+ }
1683
+
1684
+ });
1685
+
1686
+ SC.DateTime.reopenClass(SC.Comparable,
1687
+ /** @scope SC.DateTime */ {
1688
+
1689
+ /**
1690
+ The default format (ISO 8601) in which DateTimes are stored in a record.
1691
+ Change this value if your backend sends and receives dates in another
1692
+ format.
1693
+
1694
+ This value can also be customized on a per-attribute basis with the format
1695
+ property. For example:
1696
+
1697
+ SC.Record.attr(SC.DateTime, { format: '%d/%m/%Y %H:%M:%S' })
1698
+
1699
+ @type String
1700
+ @default SC.DATETIME_ISO8601
1701
+ */
1702
+ recordFormat: SC.DATETIME_ISO8601,
1703
+
1704
+ /**
1705
+ @type Array
1706
+ @default ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']
1707
+ */
1708
+ dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1709
+
1710
+ /**
1711
+ @private
1712
+
1713
+ The English day names used for the 'lastMonday', 'nextTuesday', etc., getters.
1714
+
1715
+ @type Array
1716
+ */
1717
+ _englishDayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
1718
+
1719
+ /**
1720
+ @type Array
1721
+ @default ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
1722
+ */
1723
+ abbreviatedDayNames: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
1724
+
1725
+ /**
1726
+ @type Array
1727
+ @default ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']
1728
+ */
1729
+ monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
1730
+
1731
+ /**
1732
+ @type Array
1733
+ @default ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']
1734
+ */
1735
+ abbreviatedMonthNames: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
1736
+
1737
+ /**
1738
+ @private
1739
+
1740
+ The unique internal `Date` object used to make computations. Better
1741
+ performance is obtained by having only one Date object for the whole
1742
+ application and manipulating it with `setTime()` and `getTime()`.
1743
+
1744
+ Note that since this is used for internal calculations across many
1745
+ `SC.DateTime` instances, it is not guaranteed to store the date/time that
1746
+ any one `SC.DateTime` instance represents. So it might be that
1747
+
1748
+ this._date.getTime() !== this._ms
1749
+
1750
+ Be sure to set it before using for internal calculations if necessary.
1751
+
1752
+ @type Date
1753
+ */
1754
+ _date: new Date(),
1755
+
1756
+ /**
1757
+ @private
1758
+
1759
+ The offset, in minutes, between UTC and the currently manipulated
1760
+ `SC.DateTime` instance.
1761
+
1762
+ @type Integer
1763
+ */
1764
+ _tz: 0,
1765
+
1766
+ /**
1767
+ The offset, in minutes, between UTC and the local system time. This
1768
+ property is computed at loading time and should never be changed.
1769
+
1770
+ @type Integer
1771
+ @default new Date().getTimezoneOffset()
1772
+ @constant
1773
+ */
1774
+ timezone: new Date().getTimezoneOffset(),
1775
+
1776
+ /**
1777
+ @private
1778
+
1779
+ A cache of `SC.DateTime` instances. If you attempt to create a `SC.DateTime`
1780
+ instance that has already been created, then it will return the cached
1781
+ value.
1782
+
1783
+ @type Array
1784
+ */
1785
+ _dt_cache: {},
1786
+
1787
+ /**
1788
+ @private
1789
+
1790
+ The index of the lastest cached value. Used with `_DT_CACHE_MAX_LENGTH` to
1791
+ limit the size of the cache.
1792
+
1793
+ @type Integer
1794
+ */
1795
+ _dt_cache_index: -1,
1796
+
1797
+ /**
1798
+ @private
1799
+
1800
+ The maximum length of `_dt_cache`. If this limit is reached, then the cache
1801
+ is overwritten, starting with the oldest element.
1802
+
1803
+ @type Integer
1804
+ */
1805
+ _DT_CACHE_MAX_LENGTH: 1000,
1806
+
1807
+ /**
1808
+ @private
1809
+
1810
+ Both args are optional, but will only overwrite `_date` and `_tz` if
1811
+ defined. This method does not affect the DateTime instance's actual time,
1812
+ but simply initializes the one `_date` instance to a time relevant for a
1813
+ calculation. (`this._date` is just a resource optimization)
1814
+
1815
+ This is mainly used as a way to store a recursion starting state during
1816
+ internal calculations.
1817
+
1818
+ 'milliseconds' is time since Jan 1, 1970.
1819
+ 'timezone' is the current time zone we want to be working in internally.
1820
+
1821
+ Returns a hash of the previous milliseconds and time zone in case they
1822
+ are wanted for later restoration.
1823
+ */
1824
+ _setCalcState: function(ms, timezone) {
1825
+ var previous = {
1826
+ milliseconds: this._date.getTime(),
1827
+ timezone: this._tz
1828
+ };
1829
+
1830
+ if (ms !== undefined) this._date.setTime(ms);
1831
+ if (timezone !== undefined) this._tz = timezone;
1832
+
1833
+ return previous;
1834
+ },
1835
+
1836
+ /**
1837
+ @private
1838
+
1839
+ By this time, any time zone setting on 'hash' will be ignored.
1840
+ 'timezone' will be used, or the last this._tz.
1841
+ */
1842
+ _setCalcStateFromHash: function(hash, timezone) {
1843
+ var tz = (timezone !== undefined) ? timezone : this._tz; // use the last-known time zone if necessary
1844
+ var ms = this._toMilliseconds(hash, this._ms, tz); // convert the hash (local to specified time zone) to milliseconds (in UTC)
1845
+ return this._setCalcState(ms, tz); // now call the one we really wanted
1846
+ },
1847
+
1848
+ /**
1849
+ @private
1850
+ @see SC.DateTime#unknownProperty
1851
+ */
1852
+ _get: function(key, start, timezone) {
1853
+ var ms, tz, doy, m, y, firstDayOfWeek, dayOfWeek, dayOfYear, prefix, suffix;
1854
+ var currentWeekday, targetWeekday;
1855
+ var d = this._date;
1856
+ var originalTime, v = null;
1857
+
1858
+ // Set up an absolute date/time using the given milliseconds since Jan 1, 1970.
1859
+ // Only do it if we're given a time value, though, otherwise we want to use the
1860
+ // last one we had because this `_get()` method is recursive.
1861
+ //
1862
+ // Note that because these private time calc methods are recursive, and because all DateTime instances
1863
+ // share an internal this._date and `this._tz` state for doing calculations, methods
1864
+ // that modify `this._date` or `this._tz` should restore the last state before exiting
1865
+ // to avoid obscure calculation bugs. So we save the original state here, and restore
1866
+ // it before returning at the end.
1867
+ originalTime = this._setCalcState(start, timezone); // save so we can restore it to how it was before we got here
1868
+
1869
+ // Check this first because it is an absolute value -- no tweaks necessary when calling for milliseconds
1870
+ if (key === 'milliseconds') {
1871
+ v = d.getTime();
1872
+ }
1873
+ else if (key === 'timezone') {
1874
+ v = this._tz;
1875
+ }
1876
+
1877
+ // 'nextWeekday' or 'lastWeekday'.
1878
+ // We want to do this calculation in local time, before shifting UTC below.
1879
+ if (v === null) {
1880
+ prefix = key.slice(0, 4);
1881
+ suffix = key.slice(4);
1882
+ if (prefix === 'last' || prefix === 'next') {
1883
+ currentWeekday = this._get('dayOfWeek', start, timezone);
1884
+ targetWeekday = this._englishDayNames.indexOf(suffix);
1885
+ if (targetWeekday >= 0) {
1886
+ var delta = targetWeekday - currentWeekday;
1887
+ if (prefix === 'last' && delta >= 0) delta -= 7;
1888
+ if (prefix === 'next' && delta < 0) delta += 7;
1889
+ this._advance({ day: delta }, start, timezone);
1890
+ v = this._createFromCurrentState();
1891
+ }
1892
+ }
1893
+ }
1894
+
1895
+ if (v === null) {
1896
+ // need to adjust for alternate display time zone.
1897
+ // Before calculating, we need to get everything into a common time zone to
1898
+ // negate the effects of local machine time (so we can use all the 'getUTC...() methods on Date).
1899
+ if (timezone !== undefined) {
1900
+ this._setCalcState(d.getTime() - (timezone * 60000), 0); // make this instance's time zone the new UTC temporarily
1901
+ }
1902
+
1903
+ // simple keys
1904
+ switch (key) {
1905
+ case 'year':
1906
+ v = d.getUTCFullYear(); //TODO: investigate why some libraries do getFullYear().toString() or getFullYear()+""
1907
+ break;
1908
+ case 'month':
1909
+ v = d.getUTCMonth()+1; // January is 0 in JavaScript
1910
+ break;
1911
+ case 'day':
1912
+ v = d.getUTCDate();
1913
+ break;
1914
+ case 'dayOfWeek':
1915
+ v = d.getUTCDay();
1916
+ break;
1917
+ case 'hour':
1918
+ v = d.getUTCHours();
1919
+ break;
1920
+ case 'minute':
1921
+ v = d.getUTCMinutes();
1922
+ break;
1923
+ case 'second':
1924
+ v = d.getUTCSeconds();
1925
+ break;
1926
+ case 'millisecond':
1927
+ v = d.getUTCMilliseconds();
1928
+ break;
1929
+ }
1930
+
1931
+ // isLeapYear
1932
+ if ((v === null) && (key === 'isLeapYear')) {
1933
+ y = this._get('year');
1934
+ v = (y%4 === 0 && y%100 !== 0) || y%400 === 0;
1935
+ }
1936
+
1937
+ // daysInMonth
1938
+ if ((v === null) && (key === 'daysInMonth')) {
1939
+ switch (this._get('month')) {
1940
+ case 4:
1941
+ case 6:
1942
+ case 9:
1943
+ case 11:
1944
+ v = 30;
1945
+ break;
1946
+ case 2:
1947
+ v = this._get('isLeapYear') ? 29 : 28;
1948
+ break;
1949
+ default:
1950
+ v = 31;
1951
+ break;
1952
+ }
1953
+ }
1954
+
1955
+ // dayOfYear
1956
+ if ((v === null) && (key === 'dayOfYear')) {
1957
+ ms = d.getTime(); // save time
1958
+ doy = this._get('day');
1959
+ this._setCalcStateFromHash({ day: 1 });
1960
+ for (m = this._get('month') - 1; m > 0; m--) {
1961
+ this._setCalcStateFromHash({ month: m });
1962
+ doy += this._get('daysInMonth');
1963
+ }
1964
+ d.setTime(ms); // restore time
1965
+ v = doy;
1966
+ }
1967
+
1968
+ // week, week0 or week1
1969
+ if ((v === null) && (key.slice(0, 4) === 'week')) {
1970
+ // firstDayOfWeek should be 0 (Sunday) or 1 (Monday)
1971
+ firstDayOfWeek = key.length === 4 ? 1 : parseInt(key.slice('4'), 10);
1972
+ dayOfWeek = this._get('dayOfWeek');
1973
+ dayOfYear = this._get('dayOfYear') - 1;
1974
+ if (firstDayOfWeek === 0) {
1975
+ v = parseInt((dayOfYear - dayOfWeek + 7) / 7, 10);
1976
+ }
1977
+ else {
1978
+ v = parseInt((dayOfYear - (dayOfWeek - 1 + 7) % 7 + 7) / 7, 10);
1979
+ }
1980
+ }
1981
+ }
1982
+
1983
+ // restore the internal calculation state in case someone else was in the
1984
+ // middle of a calculation (we might be recursing).
1985
+ this._setCalcState(originalTime.milliseconds, originalTime.timezone);
1986
+
1987
+ return v;
1988
+ },
1989
+
1990
+ /**
1991
+ @private
1992
+
1993
+ Sets the internal calculation state to something specified.
1994
+ */
1995
+ _adjust: function(options, start, timezone, resetCascadingly) {
1996
+ var opts = options ? copy(options) : {};
1997
+ var ms = this._toMilliseconds(options, start, timezone, resetCascadingly);
1998
+ this._setCalcState(ms, timezone);
1999
+ return this; // for chaining
2000
+ },
2001
+
2002
+ /**
2003
+ @private
2004
+ @see SC.DateTime#advance
2005
+ */
2006
+ _advance: function(options, start, timezone) {
2007
+ var opts = options ? copy(options) : {};
2008
+ var tz;
2009
+
2010
+ for (var key in opts) {
2011
+ opts[key] += this._get(key, start, timezone);
2012
+ }
2013
+
2014
+ // The time zone can be advanced by a delta as well, so try to use the
2015
+ // new value if there is one.
2016
+ tz = (opts.timezone !== undefined) ? opts.timezone : timezone; // watch out for zero, which is acceptable as a time zone
2017
+
2018
+ return this._adjust(opts, start, tz, NO);
2019
+ },
2020
+
2021
+ /*
2022
+ @private
2023
+
2024
+ Converts a standard date/time options hash to an integer representing that position
2025
+ in time relative to Jan 1, 1970
2026
+ */
2027
+ _toMilliseconds: function(options, start, timezone, resetCascadingly) {
2028
+ var opts = options ? copy(options) : {};
2029
+ var d = this._date;
2030
+ var previousMilliseconds = d.getTime(); // rather than create a new Date object, we'll reuse the instance we have for calculations, then restore it
2031
+ var ms, tz;
2032
+
2033
+ // Initialize our internal for-calculations Date object to our current date/time.
2034
+ // Note that this object was created in the local machine time zone, so when we set
2035
+ // its params later, it will be assuming these values to be in the same time zone as it is.
2036
+ // It's ok for start to be null, in which case we'll just keep whatever we had in 'd' before.
2037
+ if (!SC.none(start)) {
2038
+ d.setTime(start); // using milliseconds here specifies an absolute location in time, regardless of time zone, so that's nice
2039
+ }
2040
+
2041
+ // We have to get all time expressions, both in 'options' (assume to be in time zone 'timezone')
2042
+ // and in 'd', to the same time zone before we can any calculations correctly. So because the Date object provides
2043
+ // a suite of UTC getters and setters, we'll temporarily redefine 'timezone' as our new
2044
+ // 'UTC', so we don't have to worry about local machine time. We do this by subtracting
2045
+ // milliseconds for the time zone offset. Then we'll do all our calculations, then convert
2046
+ // it back to real UTC.
2047
+
2048
+ // (Zero time zone is considered a valid value.)
2049
+ tz = (timezone !== undefined) ? timezone : (this.timezone !== undefined) ? this.timezone : 0;
2050
+ d.setTime(d.getTime() - (tz * 60000)); // redefine 'UTC' to establish a new local absolute so we can use all the 'getUTC...()' Date methods
2051
+
2052
+ // the time options (hour, minute, sec, millisecond)
2053
+ // reset cascadingly (see documentation)
2054
+ if (resetCascadingly === undefined || resetCascadingly === YES) {
2055
+ if ( !SC.none(opts.hour) && SC.none(opts.minute)) {
2056
+ opts.minute = 0;
2057
+ }
2058
+ if (!(SC.none(opts.hour) && SC.none(opts.minute))
2059
+ && SC.none(opts.second)) {
2060
+ opts.second = 0;
2061
+ }
2062
+ if (!(SC.none(opts.hour) && SC.none(opts.minute) && SC.none(opts.second))
2063
+ && SC.none(opts.millisecond)) {
2064
+ opts.millisecond = 0;
2065
+ }
2066
+ }
2067
+
2068
+ // Get the current values for any not provided in the options hash.
2069
+ // Since everything is in 'UTC' now, use the UTC accessors. We do this because,
2070
+ // according to javascript Date spec, you have to set year, month, and day together
2071
+ // if you're setting any one of them. So we'll use the provided Date.UTC() method
2072
+ // to get milliseconds, and we need to get any missing values first...
2073
+ if (SC.none(opts.year)) opts.year = d.getUTCFullYear();
2074
+ if (SC.none(opts.month)) opts.month = d.getUTCMonth() + 1; // January is 0 in JavaScript
2075
+ if (SC.none(opts.day)) opts.day = d.getUTCDate();
2076
+ if (SC.none(opts.hour)) opts.hour = d.getUTCHours();
2077
+ if (SC.none(opts.minute)) opts.minute = d.getUTCMinutes();
2078
+ if (SC.none(opts.second)) opts.second = d.getUTCSeconds();
2079
+ if (SC.none(opts.millisecond)) opts.millisecond = d.getUTCMilliseconds();
2080
+
2081
+ // Ask the JS Date to calculate milliseconds for us (still in redefined UTC). It
2082
+ // is best to set them all together because, for example, a day value means different things
2083
+ // to the JS Date object depending on which month or year it is. It can now handle that stuff
2084
+ // internally as it's made to do.
2085
+ ms = Date.UTC(opts.year, opts.month - 1, opts.day, opts.hour, opts.minute, opts.second, opts.millisecond);
2086
+
2087
+ // Now that we've done all our calculations in a common time zone, add back the offset
2088
+ // to move back to real UTC.
2089
+ d.setTime(ms + (tz * 60000));
2090
+ ms = d.getTime(); // now get the corrected milliseconds value
2091
+
2092
+ // Restore what was there previously before leaving in case someone called this method
2093
+ // in the middle of another calculation.
2094
+ d.setTime(previousMilliseconds);
2095
+
2096
+ return ms;
2097
+ },
2098
+
2099
+ /**
2100
+ Returns a new `SC.DateTime` object advanced according the the given parameters.
2101
+ The parameters can be:
2102
+
2103
+ - none, to create a `SC.DateTime` instance initialized to the current
2104
+ date and time in the local timezone,
2105
+ - a integer, the number of milliseconds since
2106
+ January, 1st 1970 00:00:00.0 UTC
2107
+ - a options hash that can contain any of the following properties: year,
2108
+ month, day, hour, minute, second, millisecond, timezone
2109
+
2110
+ Note that if you attempt to create a `SC.DateTime` instance that has already
2111
+ been created, then, for performance reasons, a cached value may be
2112
+ returned.
2113
+
2114
+ The timezone option is the offset, in minutes, between UTC and local time.
2115
+ If you don't pass a timezone option, the date object is created in the
2116
+ local timezone. If you want to create a UTC+2 (CEST) date, for example,
2117
+ then you should pass a timezone of -120.
2118
+
2119
+ @param options one of the three kind of parameters descibed above
2120
+ @returns {SC.DateTime} the SC.DateTime instance that corresponds to the
2121
+ passed parameters, possibly fetched from cache
2122
+ */
2123
+ create: function() {
2124
+ var arg = arguments.length === 0 ? {} : arguments[0];
2125
+ var timezone;
2126
+
2127
+ // if simply milliseconds since Jan 1, 1970 are given, just use those
2128
+ if (SC.typeOf(arg) === 'number') {
2129
+ arg = { milliseconds: arg };
2130
+ }
2131
+
2132
+ // Default to local machine time zone if none is given
2133
+ timezone = (arg.timezone !== undefined) ? arg.timezone : this.timezone;
2134
+ if (timezone === undefined) timezone = 0;
2135
+
2136
+ // Desired case: create with milliseconds if we have them.
2137
+ // If we don't, convert what we have to milliseconds and recurse.
2138
+ if (!SC.none(arg.milliseconds)) {
2139
+
2140
+ // quick implementation of a FIFO set for the cache
2141
+ var key = 'nu' + arg.milliseconds + timezone, cache = this._dt_cache;
2142
+ var ret = cache[key];
2143
+ if (!ret) {
2144
+ var previousKey, idx = this._dt_cache_index;
2145
+ ret = cache[key] = this._super({ _ms: arg.milliseconds, timezone: timezone });
2146
+ idx = this._dt_cache_index = (idx + 1) % this._DT_CACHE_MAX_LENGTH;
2147
+ previousKey = cache[idx];
2148
+ if (previousKey !== undefined && cache[previousKey]) delete cache[previousKey];
2149
+ cache[idx] = key;
2150
+ }
2151
+ return ret;
2152
+ }
2153
+ // otherwise, convert what we have to milliseconds and try again
2154
+ else {
2155
+ var now = new Date();
2156
+
2157
+ return this.create({ // recursive call with new arguments
2158
+ milliseconds: this._toMilliseconds(arg, now.getTime(), timezone, arg.resetCascadingly),
2159
+ timezone: timezone
2160
+ });
2161
+ }
2162
+ },
2163
+
2164
+ /**
2165
+ @private
2166
+
2167
+ Calls the `create()` method with the current internal `_date` value.
2168
+
2169
+ @return {SC.DateTime} the SC.DateTime instance returned by create()
2170
+ */
2171
+ _createFromCurrentState: function() {
2172
+ return this.create({
2173
+ milliseconds: this._date.getTime(),
2174
+ timezone: this._tz
2175
+ });
2176
+ },
2177
+
2178
+ /**
2179
+ Returns a `SC.DateTime` object created from a given string parsed with a given
2180
+ format. Returns `null` if the parsing fails.
2181
+
2182
+ @see SC.DateTime#toFormattedString for a description of the format parameter
2183
+ @param {String} str the string to parse
2184
+ @param {String} fmt the format to parse the string with
2185
+ @returns {DateTime} the DateTime corresponding to the string parameter
2186
+ */
2187
+ parse: function(str, fmt) {
2188
+ // Declared as an object not a literal since in some browsers the literal
2189
+ // retains state across function calls
2190
+ var re = new RegExp('(?:%([aAbBcdDhHiIjmMpsSUWwxXyYZ%])|(.))', "g");
2191
+ var d, parts, opts = {}, check = {}, scanner = Scanner.create({string: str});
2192
+
2193
+ if (SC.none(fmt)) fmt = SC.DATETIME_ISO8601;
2194
+
2195
+ try {
2196
+ while ((parts = re.exec(fmt)) !== null) {
2197
+ switch(parts[1]) {
2198
+ case 'a': check.dayOfWeek = scanner.scanArray(this.abbreviatedDayNames); break;
2199
+ case 'A': check.dayOfWeek = scanner.scanArray(this.dayNames); break;
2200
+ case 'b': opts.month = scanner.scanArray(this.abbreviatedMonthNames) + 1; break;
2201
+ case 'B': opts.month = scanner.scanArray(this.monthNames) + 1; break;
2202
+ case 'c': throw new Error("%c is not implemented");
2203
+ case 'd':
2204
+ case 'D': opts.day = scanner.scanInt(1, 2); break;
2205
+ case 'h':
2206
+ case 'H': opts.hour = scanner.scanInt(1, 2); break;
2207
+ case 'i':
2208
+ case 'I': opts.hour = scanner.scanInt(1, 2); break;
2209
+ case 'j': throw new Error("%j is not implemented");
2210
+ case 'm': opts.month = scanner.scanInt(1, 2); break;
2211
+ case 'M': opts.minute = scanner.scanInt(1, 2); break;
2212
+ case 'p': opts.meridian = scanner.scanArray(['AM', 'PM']); break;
2213
+ case 'S': opts.second = scanner.scanInt(1, 2); break;
2214
+ case 's': opts.millisecond = scanner.scanInt(1, 3); break;
2215
+ case 'U': throw new Error("%U is not implemented");
2216
+ case 'W': throw new Error("%W is not implemented");
2217
+ case 'w': throw new Error("%w is not implemented");
2218
+ case 'x': throw new Error("%x is not implemented");
2219
+ case 'X': throw new Error("%X is not implemented");
2220
+ case 'y': opts.year = scanner.scanInt(2); opts.year += (opts.year > 70 ? 1900 : 2000); break;
2221
+ case 'Y': opts.year = scanner.scanInt(4); break;
2222
+ case 'Z':
2223
+ var modifier = scanner.scan(1);
2224
+ if (modifier === 'Z') {
2225
+ opts.timezone = 0;
2226
+ } else if (modifier === '+' || modifier === '-' ) {
2227
+ var h = scanner.scanInt(2);
2228
+ if (scanner.scan(1) !== ':') scanner.scan(-1);
2229
+ var m = scanner.scanInt(2);
2230
+ opts.timezone = (modifier === '+' ? -1 : 1) * (h*60 + m);
2231
+ }
2232
+ break;
2233
+ case '%': scanner.skipString('%'); break;
2234
+ default: scanner.skipString(parts[0]); break;
2235
+ }
2236
+ }
2237
+ } catch (e) {
2238
+ SC.Logger.log('SC.DateTime.createFromString ' + e.toString());
2239
+ return null;
2240
+ }
2241
+
2242
+ if (!SC.none(opts.meridian) && !SC.none(opts.hour)) {
2243
+ if (opts.meridian === 1) opts.hour = (opts.hour + 12) % 24;
2244
+ delete opts.meridian;
2245
+ }
2246
+
2247
+ d = SC.DateTime.create(opts);
2248
+
2249
+ if (!SC.none(check.dayOfWeek) && get(d,'dayOfWeek') !== check.dayOfWeek) {
2250
+ return null;
2251
+ }
2252
+
2253
+ return d;
2254
+ },
2255
+
2256
+ /**
2257
+ @private
2258
+
2259
+ Converts the x parameter into a string padded with 0s so that the string’s
2260
+ length is at least equal to the len parameter.
2261
+
2262
+ @param {Object} x the object to convert to a string
2263
+ @param {Integer} the minimum length of the returned string
2264
+ @returns {String} the padded string
2265
+ */
2266
+ _pad: function(x, len) {
2267
+ var str = '' + x;
2268
+ if (len === undefined) len = 2;
2269
+ while (str.length < len) str = '0' + str;
2270
+ return str;
2271
+ },
2272
+
2273
+ /**
2274
+ @private
2275
+ @see SC.DateTime#_toFormattedString
2276
+ */
2277
+ __toFormattedString: function(part, start, timezone) {
2278
+ var hour, offset;
2279
+
2280
+ // Note: all calls to _get() here should include only one
2281
+ // argument, since _get() is built for recursion and behaves differently
2282
+ // if arguments 2 and 3 are included.
2283
+ //
2284
+ // This method is simply a helper for this._toFormattedString() (one underscore);
2285
+ // this is only called from there, and _toFormattedString() has already
2286
+ // set up the appropriate internal date/time/timezone state for it.
2287
+
2288
+ switch(part[1]) {
2289
+ case 'a': return this.abbreviatedDayNames[this._get('dayOfWeek')];
2290
+ case 'A': return this.dayNames[this._get('dayOfWeek')];
2291
+ case 'b': return this.abbreviatedMonthNames[this._get('month')-1];
2292
+ case 'B': return this.monthNames[this._get('month')-1];
2293
+ case 'c': return this._date.toString();
2294
+ case 'd': return this._pad(this._get('day'));
2295
+ case 'D': return this._get('day');
2296
+ case 'h': return this._get('hour');
2297
+ case 'H': return this._pad(this._get('hour'));
2298
+ case 'i':
2299
+ hour = this._get('hour');
2300
+ return (hour === 12 || hour === 0) ? 12 : (hour + 12) % 12;
2301
+ case 'I':
2302
+ hour = this._get('hour');
2303
+ return this._pad((hour === 12 || hour === 0) ? 12 : (hour + 12) % 12);
2304
+ case 'j': return this._pad(this._get('dayOfYear'), 3);
2305
+ case 'm': return this._pad(this._get('month'));
2306
+ case 'M': return this._pad(this._get('minute'));
2307
+ case 'p': return this._get('hour') > 11 ? 'PM' : 'AM';
2308
+ case 'S': return this._pad(this._get('second'));
2309
+ case 's': return this._pad(this._get('millisecond'), 3);
2310
+ case 'u': return this._pad(this._get('utc')); //utc
2311
+ case 'U': return this._pad(this._get('week0'));
2312
+ case 'W': return this._pad(this._get('week1'));
2313
+ case 'w': return this._get('dayOfWeek');
2314
+ case 'x': return this._date.toDateString();
2315
+ case 'X': return this._date.toTimeString();
2316
+ case 'y': return this._pad(this._get('year') % 100);
2317
+ case 'Y': return this._get('year');
2318
+ case 'Z':
2319
+ offset = -1 * timezone;
2320
+ return (offset >= 0 ? '+' : '-')
2321
+ + this._pad(parseInt(Math.abs(offset)/60, 10))
2322
+ + ':'
2323
+ + this._pad(Math.abs(offset)%60);
2324
+ case '%': return '%';
2325
+ }
2326
+ },
2327
+
2328
+ /**
2329
+ @private
2330
+ @see SC.DateTime#toFormattedString
2331
+ */
2332
+ _toFormattedString: function(format, start, timezone) {
2333
+ var that = this;
2334
+ var tz = (timezone !== undefined) ? timezone : (this.timezone !== undefined) ? this.timezone : 0;
2335
+
2336
+ // need to move into local time zone for these calculations
2337
+ this._setCalcState(start - (timezone * 60000), 0); // so simulate a shifted 'UTC' time
2338
+
2339
+ return format.replace(/\%([aAbBcdDhHiIjmMpsSUWwxXyYZ\%])/g, function() {
2340
+ var v = that.__toFormattedString.call(that, arguments, start, timezone);
2341
+ return v;
2342
+ });
2343
+ },
2344
+
2345
+ /**
2346
+ This will tell you which of the two passed `DateTime` is greater by
2347
+ comparing their number of milliseconds since
2348
+ January, 1st 1970 00:00:00.0 UTC.
2349
+
2350
+ @param {SC.DateTime} a the first DateTime instance
2351
+ @param {SC.DateTime} b the second DateTime instance
2352
+ @returns {Integer} -1 if a < b,
2353
+ +1 if a > b,
2354
+ 0 if a == b
2355
+ */
2356
+ compare: function(a, b) {
2357
+ var ma = get(a, 'milliseconds');
2358
+ var mb = get(b, 'milliseconds');
2359
+ return ma < mb ? -1 : ma === mb ? 0 : 1;
2360
+ },
2361
+
2362
+ /**
2363
+ This will tell you which of the two passed DateTime is greater
2364
+ by only comparing the date parts of the passed objects. Only dates
2365
+ with the same timezone can be compared.
2366
+
2367
+ @param {SC.DateTime} a the first DateTime instance
2368
+ @param {SC.DateTime} b the second DateTime instance
2369
+ @returns {Integer} -1 if a < b,
2370
+ +1 if a > b,
2371
+ 0 if a == b
2372
+ @throws {SC.DATETIME_COMPAREDATE_TIMEZONE_ERROR} if the passed arguments
2373
+ don't have the same timezone
2374
+ */
2375
+ compareDate: function(a, b) {
2376
+ if (get(a, 'timezone') !== get(b,'timezone')) {
2377
+ throw new Error(SC.DATETIME_COMPAREDATE_TIMEZONE_ERROR);
2378
+ }
2379
+
2380
+ var ma = get(a.adjust({hour: 0}), 'milliseconds');
2381
+ var mb = get(b.adjust({hour: 0}), 'milliseconds');
2382
+ return ma < mb ? -1 : ma === mb ? 0 : 1;
2383
+ }
2384
+
2385
+ });
2386
+
2387
+ /**
2388
+ Adds a transform to format the DateTime value to a String value according
2389
+ to the passed format string.
2390
+
2391
+ valueBinding: SC.Binding.dateTime('%Y-%m-%d %H:%M:%S')
2392
+ .from('MyApp.myController.myDateTime');
2393
+
2394
+ @param {String} format format string
2395
+ @returns {SC.Binding} this
2396
+ */
2397
+ SC.Binding.dateTime = function(format) {
2398
+ return this.transform(function(value, binding) {
2399
+ return value ? value.toFormattedString(format) : null;
2400
+ });
2401
+ };
2402
+
2403
+
2404
+ })({});
2405
+
2406
+
2407
+ (function(exports) {
2408
+ // ==========================================================================
2409
+ // Project: SproutCore DataStore
2410
+ // Copyright: ©2010 Strobe Inc. and contributors
2411
+ // License: Licensed under MIT license (see license.js)
2412
+ // ==========================================================================
2413
+
2414
+ })({});
2415
+
2416
+ (function(exports) {
2417
+ // ==========================================================================
2418
+ // Project: SproutCore - JavaScript Application Framework
2419
+ // Copyright: ©2006-2011 Strobe Inc. and contributors.
2420
+ // Portions ©2008-2011 Apple Inc. All rights reserved.
2421
+ // License: Licensed under MIT license (see license.js)
2422
+ // ==========================================================================
2423
+
1254
2424
 
1255
2425
  var get = SC.get, set = SC.set, getPath = SC.getPath;
1256
2426
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: rasputin
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.5.1
5
+ version: 0.5.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Paul Chavard
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-07-31 00:00:00 Z
13
+ date: 2011-08-01 00:00:00 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: railties
@@ -57,6 +57,7 @@ extra_rdoc_files: []
57
57
  files:
58
58
  - .gitignore
59
59
  - Gemfile
60
+ - Gemfile.lock
60
61
  - README.md
61
62
  - Rakefile
62
63
  - lib/rasputin.rb