]> git.andy128k.dev Git - missing-tools.git/commitdiff
date format
authorAndrey Kutejko <andy128k@gmail.com>
Fri, 29 Nov 2013 00:24:57 +0000 (02:24 +0200)
committerAndrey Kutejko <andy128k@gmail.com>
Fri, 29 Nov 2013 00:24:57 +0000 (02:24 +0200)
composer.json
composer.lock
src/dateformat.php [new file with mode: 0644]
t/FormatTest.php [new file with mode: 0644]

index f716ed16674ff1d0509744fc99c5e21dd2274ec0..d4bfc76ac4e579c6059d5e38e2c324ab54a2ff2b 100644 (file)
   "autoload": {
     "classmap" : ["src"]
   },
+  "require": {
+    "andy128k/pegp": "dev-master"
+  },
   "require-dev": {
     "phpunit/phpunit": "3.7.*"
-  }
+  },
+  "repositories": [
+    {
+      "type": "composer",
+      "url": "http://packages.andy128k.net/php/"
+    }
+  ]
 }
 
index 70ea7431f36b347119f4ba885a2eeb25090185dd..315cd279974714d0627287426ddd404b821683c8 100644 (file)
@@ -3,23 +3,51 @@
         "This file locks the dependencies of your project to a known state",
         "Read more about it at http://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file"
     ],
-    "hash": "8c6ef015d9701af81af1ba6dec9f4ada",
+    "hash": "70d6aba0d7196c6999d2539c4ec24481",
     "packages": [
-
+        {
+            "name": "andy128k/pegp",
+            "version": "dev-master",
+            "source": {
+                "type": "git",
+                "url": "git://git.andy128k.net/pegp.git",
+                "reference": "52db5ee8c04ec7e411af0f73aa1e54ce208d08e0"
+            },
+            "require-dev": {
+                "phpunit/phpunit": "3.7.*"
+            },
+            "type": "library",
+            "autoload": {
+                "classmap": [
+                    "lib"
+                ]
+            },
+            "license": [
+                "MIT"
+            ],
+            "authors": [
+                {
+                    "name": "Andrey Kutejko",
+                    "email": "andy128k@gmail.com"
+                }
+            ],
+            "description": "PEG",
+            "time": "2013-08-11 11:10:38"
+        }
     ],
     "packages-dev": [
         {
             "name": "phpunit/php-code-coverage",
-            "version": "1.2.12",
+            "version": "1.2.13",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-code-coverage.git",
-                "reference": "1.2.12"
+                "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/1.2.12",
-                "reference": "1.2.12",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-code-coverage/zipball/466e7cd2554b4e264c9e3f31216d25ac0e5f3d94",
+                "reference": "466e7cd2554b4e264c9e3f31216d25ac0e5f3d94",
                 "shasum": ""
             },
             "require": {
                 "testing",
                 "xunit"
             ],
-            "time": "2013-07-06 06:26:16"
+            "time": "2013-09-10 08:14:32"
         },
         {
             "name": "phpunit/php-file-iterator",
-            "version": "1.3.3",
+            "version": "1.3.4",
             "source": {
                 "type": "git",
-                "url": "git://github.com/sebastianbergmann/php-file-iterator.git",
-                "reference": "1.3.3"
+                "url": "https://github.com/sebastianbergmann/php-file-iterator.git",
+                "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://github.com/sebastianbergmann/php-file-iterator/zipball/1.3.3",
-                "reference": "1.3.3",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-file-iterator/zipball/acd690379117b042d1c8af1fafd61bde001bf6bb",
+                "reference": "acd690379117b042d1c8af1fafd61bde001bf6bb",
                 "shasum": ""
             },
             "require": {
                 }
             ],
             "description": "FilterIterator implementation that filters files based on a list of suffixes.",
-            "homepage": "http://www.phpunit.de/",
+            "homepage": "https://github.com/sebastianbergmann/php-file-iterator/",
             "keywords": [
                 "filesystem",
                 "iterator"
             ],
-            "time": "2012-10-11 04:44:38"
+            "time": "2013-10-10 15:34:57"
         },
         {
             "name": "phpunit/php-text-template",
         },
         {
             "name": "phpunit/php-token-stream",
-            "version": "1.2.0",
+            "version": "1.2.1",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/php-token-stream.git",
-                "reference": "1.2.0"
+                "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/1.2.0",
-                "reference": "1.2.0",
+                "url": "https://api.github.com/repos/sebastianbergmann/php-token-stream/zipball/5220af2a7929aa35cf663d97c89ad3d50cf5fa3e",
+                "reference": "5220af2a7929aa35cf663d97c89ad3d50cf5fa3e",
                 "shasum": ""
             },
             "require": {
             "keywords": [
                 "tokenizer"
             ],
-            "time": "2013-08-04 05:57:48"
+            "time": "2013-09-13 04:58:23"
         },
         {
             "name": "phpunit/phpunit",
-            "version": "3.7.24",
+            "version": "3.7.28",
             "source": {
                 "type": "git",
                 "url": "https://github.com/sebastianbergmann/phpunit.git",
-                "reference": "3.7.24"
+                "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3.7.24",
-                "reference": "3.7.24",
+                "url": "https://api.github.com/repos/sebastianbergmann/phpunit/zipball/3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",
+                "reference": "3b97c8492bcafbabe6b6fbd2ab35f2f04d932a8d",
                 "shasum": ""
             },
             "require": {
                 "testing",
                 "xunit"
             ],
-            "time": "2013-08-09 06:58:24"
+            "time": "2013-10-17 07:27:40"
         },
         {
             "name": "phpunit/phpunit-mock-objects",
         },
         {
             "name": "symfony/yaml",
-            "version": "v2.3.3",
+            "version": "v2.3.7",
             "target-dir": "Symfony/Component/Yaml",
             "source": {
                 "type": "git",
                 "url": "https://github.com/symfony/Yaml.git",
-                "reference": "v2.3.3"
+                "reference": "c1bda5b459d792cb253de12c65beba3040163b2b"
             },
             "dist": {
                 "type": "zip",
-                "url": "https://api.github.com/repos/symfony/Yaml/zipball/v2.3.3",
-                "reference": "v2.3.3",
+                "url": "https://api.github.com/repos/symfony/Yaml/zipball/c1bda5b459d792cb253de12c65beba3040163b2b",
+                "reference": "c1bda5b459d792cb253de12c65beba3040163b2b",
                 "shasum": ""
             },
             "require": {
             ],
             "description": "Symfony Yaml Component",
             "homepage": "http://symfony.com",
-            "time": "2013-07-21 12:12:18"
+            "time": "2013-10-17 11:48:01"
         }
     ],
     "aliases": [
 
     ],
     "minimum-stability": "stable",
-    "stability-flags": [
-
-    ],
+    "stability-flags": {
+        "andy128k/pegp": 20
+    },
     "platform": [
 
     ],
diff --git a/src/dateformat.php b/src/dateformat.php
new file mode 100644 (file)
index 0000000..3032fbf
--- /dev/null
@@ -0,0 +1,186 @@
+<?php
+
+final class DateFormat
+{
+    const DATE_BIG_ENDIAN     =  0;
+    const DATE_LITTLE_ENDIAN  =  4;
+    const DATE_MIDDLE_ENDIAN  =  8;
+
+    const DATE_SLASHES        =  0;
+    const DATE_DOTS           =  1;
+    const DATE_HYPHENS        =  2;
+    const DATE_SPACES         =  3;
+
+    const TIME_24HOURS        = 16;
+    const TIME_12HOURS        = 32;
+    const TIME_12HOURS_UPPER  = 32;
+    const TIME_12HOURS_LOWER  = 48;
+
+    const TIME_SECONDS        = 64;
+
+    const DATE_DEFAULT        =  2; // DATE_BIG_ENDIAN    | DATE_HYPHENS
+    const DATE_US             =  8; // DATE_MIDDLE_ENDIAN | DATE_SLASHES
+    const DATE_EUROPEAN       =  5; // DATE_LITTLE_ENDIAN | DATE_DOTS
+
+    const DATETIME_DEFAULT    = 18; // DATE_DEFAULT  | TIME_24HOURS
+    const DATETIME_US         = 40; // DATE_US       | TIME_12HOURS
+    const DATETIME_EUROPEAN   = 21; // DATE_EUROPEAN | TIME_24HOURS
+
+    public static $strftimeControls, $dateControls, $pickerControls;
+
+    private static $dateSeparators;
+
+    public static function init()
+    {
+        self::$dateSeparators = array('/', '.', '-', ' ');
+
+        self::$strftimeControls = array('%Y', '%m', '%d', '%H', '%l', '%p', '%P', '%M', '%S');
+        self::$dateControls     = array( 'Y',  'm',  'd',  'H',  'h',  'A',  'a',  'i',  's');
+        self::$pickerControls   = array('yy', 'mm', 'dd', 'HH', 'hh', 'TT', 'tt', 'mm', 'ss');
+    }
+
+    public static function dateFlagsFromString($str)
+    {
+        return
+            Pegp::oneOf(
+                Pegp::stri('default')->value(self::DATE_DEFAULT),
+                Pegp::stri('us')->value(self::DATE_US),
+                Pegp::stri('european')->value(self::DATE_EUROPEAN),
+                Pegp::seq(
+                    Pegp::optional(
+                        Pegp::seq(
+                            Pegp::oneOf(
+                                Pegp::stri('big-endian')->value(self::DATE_BIG_ENDIAN),
+                                Pegp::stri('little-endian')->value(self::DATE_LITTLE_ENDIAN),
+                                Pegp::stri('middle-endian')->value(self::DATE_MIDDLE_ENDIAN)),
+                            Pegp::re('\s+')->drop())->bitOr(), 0),
+                    Pegp::oneOf(
+                        Pegp::stri('slashes')->value(self::DATE_SLASHES),
+                        Pegp::stri('dots')->value(self::DATE_DOTS),
+                        Pegp::stri('hyphens')->value(self::DATE_HYPHENS),
+                        Pegp::stri('spaces')->value(self::DATE_SPACES)))->bitOr())
+        ->parseString($str);
+    }
+
+    public static function datetimeFlagsFromString($str)
+    {
+        return
+            Pegp::oneOf(
+                Pegp::stri('default')->value(self::DATETIME_DEFAULT),
+                Pegp::stri('us')->value(self::DATETIME_US),
+                Pegp::stri('european')->value(self::DATETIME_EUROPEAN),
+                Pegp::seq(
+                    Pegp::optional(
+                        Pegp::seq(
+                            Pegp::oneOf(
+                                Pegp::stri('big-endian')->value(self::DATE_BIG_ENDIAN),
+                                Pegp::stri('little-endian')->value(self::DATE_LITTLE_ENDIAN),
+                                Pegp::stri('middle-endian')->value(self::DATE_MIDDLE_ENDIAN)),
+                            Pegp::re('\s+')->drop())->bitOr(), 0),
+                    Pegp::oneOf(
+                        Pegp::stri('slashes')->value(self::DATE_SLASHES),
+                        Pegp::stri('dots')->value(self::DATE_DOTS),
+                        Pegp::stri('hyphens')->value(self::DATE_HYPHENS),
+                        Pegp::stri('spaces')->value(self::DATE_SPACES)),
+                    Pegp::re('\s+')->drop(),
+                    Pegp::oneOf(
+                        Pegp::stri('24')->value(self::TIME_24HOURS),
+                        Pegp::stri('12-upper')->value(self::TIME_12HOURS_UPPER),
+                        Pegp::stri('12-lower')->value(self::TIME_12HOURS_LOWER),
+                        Pegp::stri('12')->value(self::TIME_12HOURS)),
+                    Pegp::optional(
+                        Pegp::seq(
+                            Pegp::re('\s+')->drop(),
+                            Pegp::stri('seconds'))->value(self::TIME_SECONDS), 0))->bitOr())
+        ->parseString($str);
+    }
+
+    /**
+     * Builds format string corresponding to given flags and controls.
+     *
+     * @param  integer Format flags
+     * @param  array Format values.
+     *    Examples:
+     *      array(
+     *        'Y', // year
+     *        'm', // month
+     *        'd', // day
+     *      )
+     *      array(
+     *        '%Y',                   // year
+     *        '%m',                   // month
+     *        '%d',                   // day
+     *        '%H', '%l', '%p', '%P', // hour-24, hour-12, AM/PM, am/pm
+     *        '%M',                   // minute
+     *        '%S',                   // second
+     *      )
+     * @return string Format string
+     */
+    public static function makeFormat($flags, $controls)
+    {
+        $date = self::makeDateFormat($flags, $controls);
+        $time = self::makeTimeFormat($flags, $controls);
+        if ($time)
+            return $date . ' ' . $time;
+        else
+            return $date;
+    }
+
+    public static function makeDateFormat($flags, $controls)
+    {
+        $separator = self::$dateSeparators[$flags % 4];
+        switch ($flags & 12) {
+            case self::DATE_BIG_ENDIAN:
+                return $controls[0].$separator.$controls[1].$separator.$controls[2];
+            case self::DATE_LITTLE_ENDIAN:
+                return $controls[2].$separator.$controls[1].$separator.$controls[0];
+            case self::DATE_MIDDLE_ENDIAN:
+                return $controls[1].$separator.$controls[2].$separator.$controls[0];
+            default:
+                throw new Exception('Bad date format');
+        }
+    }
+
+    public static function makeTimeFormat($flags, $controls)
+    {
+        if (!($flags & 112)) // no time flags
+            return '';
+
+        $seconds = $flags & self::TIME_SECONDS;
+        switch ($flags & 48) {
+            case self::TIME_24HOURS:
+                $result = $controls[3].':'.$controls[7];
+                if ($seconds)
+                    $result .= ':'.$controls[8];
+                break;
+            case self::TIME_12HOURS_UPPER:
+                $result = $controls[4].':'.$controls[7];
+                if ($seconds)
+                    $result .= ':'.$controls[8];
+                $result .= ' '.$controls[5];
+                break;
+            case self::TIME_12HOURS_LOWER:
+                $result = $controls[4].':'.$controls[7];
+                if ($seconds)
+                    $result .= ':'.$controls[8];
+                $result .= ' '.$controls[6];
+                break;
+            default:
+                throw new Exception('Bad time format');
+        }
+        return $result;
+    }
+
+    public static function parseDate($format, $str)
+    {
+        return strptime($str, self::makeFormat($format, self::$strftimeControls));
+    }
+
+    public static function formatDate($format, $timestamp)
+    {
+        return strftime(self::makeFormat($format, self::$strftimeControls), $timestamp);
+    }
+}
+
+DateFormat::init();
+
diff --git a/t/FormatTest.php b/t/FormatTest.php
new file mode 100644 (file)
index 0000000..2f6245f
--- /dev/null
@@ -0,0 +1,36 @@
+<?php
+
+class Format_Test extends PHPUnit_Framework_TestCase
+{
+    public function testFlags()
+    {
+        $this->assertEquals(DateFormat::DATE_DEFAULT,  DateFormat::DATE_BIG_ENDIAN    | DateFormat::DATE_HYPHENS);
+        $this->assertEquals(DateFormat::DATE_US,       DateFormat::DATE_MIDDLE_ENDIAN | DateFormat::DATE_SLASHES);
+        $this->assertEquals(DateFormat::DATE_EUROPEAN, DateFormat::DATE_LITTLE_ENDIAN | DateFormat::DATE_DOTS);
+    }
+
+    public function testDateFlagsFromString()
+    {
+        $this->assertEquals(DateFormat::DATE_DEFAULT,  DateFormat::dateFlagsFromString('Default'));
+        $this->assertEquals(DateFormat::DATE_DEFAULT,  DateFormat::dateFlagsFromString('Big-endian hyphEns'));
+        $this->assertEquals(DateFormat::DATE_EUROPEAN, DateFormat::dateFlagsFromString('European'));
+        $this->assertEquals(DateFormat::DATE_EUROPEAN, DateFormat::dateFlagsFromString('little-endian dots'));
+        $this->assertEquals(DateFormat::DATE_US,       DateFormat::dateFlagsFromString('US'));
+        $this->assertEquals(DateFormat::DATE_US,       DateFormat::dateFlagsFromString('Middle-Endian Slashes'));
+        $this->assertEquals(DateFormat::DATE_BIG_ENDIAN | DateFormat::DATE_SPACES,
+                                                       DateFormat::dateFlagsFromString('big-endian spaces'));
+    }
+
+    public function testDatetimeFlagsFromString()
+    {
+        $this->assertEquals(DateFormat::DATETIME_DEFAULT,  DateFormat::datetimeFlagsFromString('Default'));
+        $this->assertEquals(DateFormat::DATETIME_DEFAULT,  DateFormat::datetimeFlagsFromString('Big-endian hyphEns 24'));
+        $this->assertEquals(DateFormat::DATETIME_EUROPEAN, DateFormat::datetimeFlagsFromString('European'));
+        $this->assertEquals(DateFormat::DATETIME_EUROPEAN, DateFormat::datetimeFlagsFromString('little-endian dots 24'));
+        $this->assertEquals(DateFormat::DATETIME_US,       DateFormat::datetimeFlagsFromString('US'));
+        $this->assertEquals(DateFormat::DATETIME_US,       DateFormat::datetimeFlagsFromString('Middle-Endian Slashes 12-upper'));
+        $this->assertEquals(DateFormat::DATE_BIG_ENDIAN | DateFormat::DATE_SPACES | DateFormat::TIME_12HOURS_LOWER | DateFormat::TIME_SECONDS,
+                                                           DateFormat::datetimeFlagsFromString("big-endian spaces \n 12-lower Seconds"));
+    }
+}
+