MINIFICPP-472 Added date formatting EL functions

This closes #315.

Signed-off-by: Aldrin Piri <[email protected]>


Project: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/commit/8777ab5f
Tree: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/tree/8777ab5f
Diff: http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/diff/8777ab5f

Branch: refs/heads/master
Commit: 8777ab5f02cfc33e533fd9784b8721dcc5e348e7
Parents: 02f1823
Author: Andrew I. Christianson <[email protected]>
Authored: Mon Apr 30 15:41:17 2018 -0400
Committer: Aldrin Piri <[email protected]>
Committed: Fri May 18 20:06:12 2018 -0400

----------------------------------------------------------------------
 EXPRESSIONS.md                                  |   91 +-
 LICENSE                                         |   34 +
 extensions/expression-language/CMakeLists.txt   |    5 +
 extensions/expression-language/Expression.cpp   |   48 +
 extensions/expression-language/common/Value.h   |    4 +
 .../impl/expression/Expression.h                |    7 +
 .../ExpressionLanguageTests.cpp                 |   42 +
 thirdparty/date/.gitignore                      |  194 +
 thirdparty/date/CMakeLists.txt                  |  164 +
 thirdparty/date/LICENSE.txt                     |   31 +
 thirdparty/date/README.md                       |   58 +
 thirdparty/date/compile_fail.sh                 |   16 +
 thirdparty/date/include/date/chrono_io.h        |   34 +
 thirdparty/date/include/date/date.h             | 8022 ++++++++++++++++++
 thirdparty/date/include/date/ios.h              |   50 +
 thirdparty/date/include/date/islamic.h          | 3031 +++++++
 thirdparty/date/include/date/iso_week.h         | 1745 ++++
 thirdparty/date/include/date/julian.h           | 3046 +++++++
 thirdparty/date/include/date/ptz.h              |  592 ++
 thirdparty/date/include/date/tz.h               | 2575 ++++++
 thirdparty/date/include/date/tz_private.h       |  318 +
 thirdparty/date/src/ios.mm                      |  337 +
 thirdparty/date/src/tz.cpp                      | 3788 +++++++++
 thirdparty/date/test_fail.sh                    |   10 +
 24 files changed, 24236 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/EXPRESSIONS.md
----------------------------------------------------------------------
diff --git a/EXPRESSIONS.md b/EXPRESSIONS.md
index 1056900..79b9e0c 100644
--- a/EXPRESSIONS.md
+++ b/EXPRESSIONS.md
@@ -236,6 +236,12 @@ token, filename.
 - [`join`](#join)
 - [`count`](#count)
 
+### Date Manipulation
+
+- [`format`](#format)
+- [`toDate`](#todate)
+- [`now`](#now)
+
 ## Planned Features
 
 ### Searching
@@ -249,12 +255,6 @@ token, filename.
 - `unescapeHtml3`
 - `unescapeHtml4`
 
-### Date Manipulation
-
-- `format`
-- `toDate`
-- `now`
-
 ### Subjectless Functions
 
 - `nextInt`
@@ -1820,3 +1820,82 @@ consider the following examples:
 | `${allDelineatedValues(${number_list}, ","):count()}` | `5` |
 | `${allAttributes("abc", "non-existent-attr", "xyz"):count()}` | `2` |
 | `${allMatchingAttributes(".*"):length():gt(10):count()}` | `2` |
+
+### format
+
+**Description**: Formats a number as a date/time according to the format
+specified by the argument. The argument must be a String that is a valid
+strftime format. The Subject is expected to be a Number that represents the
+number of milliseconds since Midnight GMT on January 1, 1970. The number will
+be evaluated using the local time zone unless specified in the second optional
+argument.
+
+**Subject Type**: Number
+
+**Arguments**:
+
+| Argument | Description |
+| - | - |
+| format | The format to use in the strftime syntax |
+| time zone | Optional argument that specifies the time zone to use from the 
IANA Time Zone Database (e.g. 'America/New_York') |
+
+**Return Type**: String
+
+**Examples**:
+
+If the attribute "time" has the value "1420058163264", then the following
+Expressions will yield the following results:
+
+| Expression | Value |
+| - | - |
+| `${time:format("%Y/%m/%d %H:%M:%S", "GMT")}` | `2014/12/31 20:36:03` |
+| `${time:format("%Y", "America/Los_Angeles")}` | `2014` |
+
+### toDate
+
+**Description**: Converts a String into a date represented by the number of
+milliseconds since the UNIX epoch, based on the format specified by the
+argument. The argument must be a String that is a valid strftime syntax. The
+Subject is expected to be a String that is formatted according the argument.
+The date will be evaluated using the local time zone unless specified in the
+second optional argument.
+
+**Subject Type**: String
+
+| format | The format to use in the strftime syntax |
+| time zone | Optional argument that specifies the time zone to use when 
parsing the subject, from the IANA Time Zone Database (e.g. 'America/New_York') 
|
+
+**Return Type**: Number
+
+**Examples**:
+
+If the attribute "year" has the value "2014" and the attribute "time" has the
+value "2014/12/31 15:36:03.264Z", then the Expression `${year:toDate('%Y',
+'GMT')}` will return a date with a value representing Midnight GMT on January
+1, 2014. The Expression `${time:toDate("%Y/%m/%d %H:%M:%S", "GMT")} will result
+in a date for 15:36:03 GMT on December 31, 2014.
+
+Often, this function is used in conjunction with the format function to change
+the format of a date/time. For example, if the attribute "date" has the value
+"12-24-2014" and we want to change the format to "2014/12/24", we can do so by
+chaining together the two functions:
+`${date:toDate('%m-%d-%Y'):format('%Y/%m/%d')}`.
+
+### now
+
+**Description**: Returns the current date and time as a Date data type object.
+
+**Subject Type**: String
+
+**Arguments**: No arguments
+
+**Return Type**: Number
+
+**Examples**:
+
+| Expression | Value |
+| - | - |
+| `${now()}` | `Count of milliseconds since the UNIX epoch` |
+| `${now():minus(86400000)` | `A number presenting the time 24 hours ago` |
+| `${now():format('Y')}` | `The current year` |
+| `${now():minus(86400000):format('%a')}` | `The day of the week that was 
yesterday, as a 3-letter abbreviation (For example, Wed)` |

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/LICENSE
----------------------------------------------------------------------
diff --git a/LICENSE b/LICENSE
index 3374acd..dfa1e2b 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1284,6 +1284,40 @@ Except as contained in this notice, the name of a 
copyright holder shall not be
 used in advertising or otherwise to promote the sale, use or other dealings in
 this Software without prior written authorization of the copyright holder.
 
+This product bundles date which is available under a MIT license:
+
+The source code in this project is released using the MIT License. There is no
+global license for the project because each file is licensed individually with
+different author names and/or dates.
+
+If you contribute to this project, please add your name to the license of each
+file you modify.  If you have already contributed to this project and forgot to
+add your name to the license, please feel free to submit a new P/R to add your
+name to the license in each file you modified.
+
+For convenience, here is a copy of the MIT license found in each file except
+without author names or dates:
+
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+
 This product bundles RapidJSON:
 Tencent is pleased to support the open source community by making RapidJSON 
available. 
  

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/extensions/expression-language/CMakeLists.txt 
b/extensions/expression-language/CMakeLists.txt
index d16b7d2..1b44302 100644
--- a/extensions/expression-language/CMakeLists.txt
+++ b/extensions/expression-language/CMakeLists.txt
@@ -41,6 +41,9 @@ add_flex_bison_dependency(el-scanner el-parser)
 include_directories(../../libminifi/include  ../../libminifi/include/core  
../../thirdparty/spdlog-20170710/include ../../thirdparty/concurrentqueue 
../../thirdparty/yaml-cpp-yaml-cpp-0.5.3/include 
${CIVET_THIRDPARTY_ROOT}/include ../../thirdparty/)
 include_directories(common)
 include_directories(impl)
+include_directories(../../thirdparty/date/include)
+
+add_subdirectory(../../thirdparty/date ${CMAKE_CURRENT_BINARY_DIR}/date)
 
 file(GLOB SOURCES  "*.cpp")
 
@@ -53,6 +56,8 @@ if(CMAKE_THREAD_LIBS_INIT)
   target_link_libraries(minifi-expression-language-extensions 
"${CMAKE_THREAD_LIBS_INIT}")
 endif()
 
+target_link_libraries(minifi-expression-language-extensions ${LIBMINIFI} tz)
+
 find_package(UUID REQUIRED)
 target_link_libraries(minifi-expression-language-extensions ${LIBMINIFI} 
${UUID_LIBRARIES})
 find_package(CURL REQUIRED)

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/Expression.cpp
----------------------------------------------------------------------
diff --git a/extensions/expression-language/Expression.cpp 
b/extensions/expression-language/Expression.cpp
index 6c5b5b0..80c9440 100644
--- a/extensions/expression-language/Expression.cpp
+++ b/extensions/expression-language/Expression.cpp
@@ -34,6 +34,10 @@
 #include "base64.h"
 #include "Driver.h"
 
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+#include "date/tz.h"
+#endif  // EXPRESSION_LANGUAGE_USE_DATE
+
 namespace org {
 namespace apache {
 namespace nifi {
@@ -1274,6 +1278,42 @@ Value expr_escapeCsv(const std::vector<Value> &args) {
   return Value(result);
 }
 
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+
+Value expr_format(const std::vector<Value> &args) {
+  std::chrono::milliseconds dur(args[0].asUnsignedLong());
+  std::chrono::time_point<std::chrono::system_clock> dt(dur);
+  auto zone = date::current_zone();
+  if (args.size() > 2) {
+    zone = date::locate_zone(args[2].asString());
+  }
+  auto t = date::make_zoned(zone, dt);
+  std::stringstream result_s;
+  result_s << date::format(args[1].asString(), t);
+  return Value(result_s.str());
+}
+
+Value expr_toDate(const std::vector<Value> &args) {
+  auto arg_0 = args[0].asString();
+  std::istringstream arg_s{arg_0};
+  date::sys_time<std::chrono::milliseconds> t;
+  arg_s >> date::parse(args[1].asString(), t);
+  auto zone = date::current_zone();
+  if (args.size() > 2) {
+    zone = date::locate_zone(args[2].asString());
+  }
+  auto utc = date::locate_zone("UTC");
+  auto utct = date::make_zoned(utc, t);
+  auto zt = date::make_zoned(zone, utct.get_local_time());
+  return 
Value(std::chrono::duration_cast<std::chrono::milliseconds>(zt.get_sys_time().time_since_epoch()).count());
+}
+
+#endif  // EXPRESSION_LANGUAGE_USE_DATE
+
+Value expr_now(const std::vector<Value> &args) {
+  return 
Value(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
+}
+
 Value expr_unescapeCsv(const std::vector<Value> &args) {
   auto result = args[0].asString();
 
@@ -2209,6 +2249,14 @@ Expression make_dynamic_function(const std::string 
&function_name,
     return make_count(function_name, args);
   } else if (function_name == "join") {
     return make_join(function_name, args);
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+  } else if (function_name == "format") {
+    return make_dynamic_function_incomplete<expr_format>(function_name, args, 
1);
+  } else if (function_name == "toDate") {
+    return make_dynamic_function_incomplete<expr_toDate>(function_name, args, 
1);
+#endif  // EXPRESSION_LANGUAGE_USE_DATE
+  } else if (function_name == "now") {
+    return make_dynamic_function_incomplete<expr_now>(function_name, args, 0);
   } else {
     std::string msg("Unknown expression function: ");
     msg.append(function_name);

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/common/Value.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/common/Value.h 
b/extensions/expression-language/common/Value.h
index 1c4ec43..d71517b 100644
--- a/extensions/expression-language/common/Value.h
+++ b/extensions/expression-language/common/Value.h
@@ -183,6 +183,10 @@ class Value {
       return unsigned_long_val_;
     } else if (is_string_) {
       return std::stoul(string_val_);
+    } else if (is_signed_long_) {
+      return signed_long_val_;
+    } else if (is_long_double_) {
+      return long_double_val_;
     } else {
       return 0.0;
     }

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/extensions/expression-language/impl/expression/Expression.h
----------------------------------------------------------------------
diff --git a/extensions/expression-language/impl/expression/Expression.h 
b/extensions/expression-language/impl/expression/Expression.h
index b7bf676..15f7558 100644
--- a/extensions/expression-language/impl/expression/Expression.h
+++ b/extensions/expression-language/impl/expression/Expression.h
@@ -25,6 +25,13 @@
 #undef EXPRESSION_LANGUAGE_USE_REGEX
 #endif
 
+#define EXPRESSION_LANGUAGE_USE_DATE
+
+// Disable date in EL for incompatible compilers
+#if __GNUC__ < 5
+#undef EXPRESSION_LANGUAGE_USE_DATE
+#endif
+
 #include <Value.h>
 #include <core/FlowFile.h>
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
----------------------------------------------------------------------
diff --git 
a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp 
b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
index 232deb4..f6e143e 100644
--- a/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
+++ b/libminifi/test/expression-language-tests/ExpressionLanguageTests.cpp
@@ -16,6 +16,8 @@
  * limitations under the License.
  */
 
+#include <time.h>
+
 #include <memory>
 #include <string>
 
@@ -1209,6 +1211,46 @@ TEST_CASE("Encode Decode URL", 
"[expressionEncodeDecodeURL]") {  // NOLINT
   REQUIRE("some value with spaces" == expr({flow_file_a}).asString());
 }
 
+#ifdef EXPRESSION_LANGUAGE_USE_DATE
+
+TEST_CASE("Parse Date", "[expressionParseDate]") {  // NOLINT
+  auto expr = expression::compile("${message:toDate('%Y/%m/%d', 
'America/Los_Angeles')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "2014/04/30");
+  REQUIRE("1398841200000" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Format Date", "[expressionFormatDate]") {  // NOLINT
+  auto expr = expression::compile("${message:format('%m-%d-%Y', 'GMT')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "1394755200000");
+  REQUIRE("03-14-2014" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Reformat Date", "[expressionReformatDate]") {  // NOLINT
+  auto expr = expression::compile("${message:toDate('%Y/%m/%d', 
'GMT'):format('%m-%d-%Y', 'America/New_York')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "2014/03/14");
+  REQUIRE("03-13-2014" == expr({flow_file_a}).asString());
+}
+
+TEST_CASE("Now Date", "[expressionNowDate]") {  // NOLINT
+  auto expr = expression::compile("${now():format('%Y')}");
+
+  auto flow_file_a = std::make_shared<MockFlowFile>();
+  flow_file_a->addAttribute("message", "2014/03/14");
+  time_t t = time(nullptr);
+  struct tm lt;
+  localtime_r(&t, &lt);
+
+  REQUIRE((lt.tm_year + 1900) == expr({flow_file_a}).asUnsignedLong());
+}
+
+#endif  // EXPRESSION_LANGUAGE_USE_DATE
+
 TEST_CASE("IP", "[expressionIP]") {  // NOLINT
   auto expr = expression::compile("${ip()}");
 

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/.gitignore
----------------------------------------------------------------------
diff --git a/thirdparty/date/.gitignore b/thirdparty/date/.gitignore
new file mode 100644
index 0000000..e88e3be
--- /dev/null
+++ b/thirdparty/date/.gitignore
@@ -0,0 +1,194 @@
+#ignore thumbnails created by windows
+Thumbs.db
+#Ignore files build by Visual Studio
+*.obj
+*.exe
+*.pdb
+*.user
+*.aps
+*.pch
+*.vspscc
+*_i.c
+*_p.c
+*.ncb
+*.suo
+*.tlb
+*.tlh
+*.bak
+*.cache
+*.ilk
+*.log
+[Bb]in
+[Dd]ebug*/
+*.lib
+*.sbr
+obj/
+[Rr]elease*/
+_ReSharper*/
+[Tt]est[Rr]esult*
+.idea/
+*.opensdf
+## Ignore Visual Studio temporary files, build results, and
+## files generated by popular Visual Studio add-ons.
+# User-specific files
+*.suo
+*.user
+*.userosscache
+*.sln.docstates
+# User-specific folders
+*.sln.ide/
+# Build results
+[Dd]ebug/
+[Dd]ebugPublic/
+[Rr]elease/
+[Rr]eleases/
+x64/
+x86/
+build/
+bld/
+[Bb]in/
+[Oo]bj/
+# Roslyn cache directories
+*.ide/
+# MSTest test Results
+[Tt]est[Rr]esult*/
+[Bb]uild[Ll]og.*
+#NUNIT
+*.VisualState.xml
+TestResult.xml
+# Build Results of an ATL Project
+[Dd]ebugPS/
+[Rr]eleasePS/
+dlldata.c
+*_i.c
+*_p.c
+*_i.h
+*.ilk
+*.meta
+*.obj
+*.pch
+*.pdb
+*.pgc
+*.pgd
+*.rsp
+*.sbr
+*.tlb
+*.tli
+*.tlh
+*.tmp
+*.tmp_proj
+*.log
+*.vspscc
+*.vssscc
+.builds
+*.pidb
+*.svclog
+*.scc
+# Chutzpah Test files
+_Chutzpah*
+# Visual C++ cache files
+ipch/
+*.aps
+*.ncb
+*.opensdf
+*.sdf
+*.cachefile
+# Visual Studio profiler
+*.psess
+*.vsp
+*.vspx
+# TFS 2012 Local Workspace
+$tf/
+# Guidance Automation Toolkit
+*.gpState
+# ReSharper is a .NET coding add-in
+_ReSharper*/
+*.[Rr]e[Ss]harper
+*.DotSettings.user
+# JustCode is a .NET coding addin-in
+.JustCode
+# TeamCity is a build add-in
+_TeamCity*
+# DotCover is a Code Coverage Tool
+*.dotCover
+# NCrunch
+_NCrunch_*
+.*crunch*.local.xml
+# MightyMoose
+*.mm.*
+AutoTest.Net/
+# Web workbench (sass)
+.sass-cache/
+# Installshield output folder
+[Ee]xpress/
+# DocProject is a documentation generator add-in
+DocProject/buildhelp/
+DocProject/Help/*.HxT
+DocProject/Help/*.HxC
+DocProject/Help/*.hhc
+DocProject/Help/*.hhk
+DocProject/Help/*.hhp
+DocProject/Help/Html2
+DocProject/Help/html
+# Click-Once directory
+publish/
+# Publish Web Output
+*.[Pp]ublish.xml
+*.azurePubxml
+# TODO: Comment the next line if you want to checkin your web deploy settings 
+# but database connection strings (with potential passwords) will be 
unencrypted
+*.pubxml
+*.publishproj
+# NuGet Packages
+*.nupkg
+# The packages folder can be ignored because of Package Restore
+**/packages/*
+# except build/, which is used as an MSBuild target.
+!**/packages/build/
+# If using the old MSBuild-Integrated Package Restore, uncomment this:
+#!**/packages/repositories.config
+# Windows Azure Build Output
+csx/
+*.build.csdef
+# Windows Store app package directory
+AppPackages/
+# Others
+sql/
+*.Cache
+ClientBin/
+[Ss]tyle[Cc]op.*
+~$*
+*~
+*.dbmdl
+*.dbproj.schemaview
+*.pfx
+*.publishsettings
+node_modules/
+bower_components/
+# RIA/Silverlight projects
+Generated_Code/
+# Backup & report files from converting an old project file
+# to a newer Visual Studio version. Backup files are not needed,
+# because we have git ;-)
+_UpgradeReport_Files/
+Backup*/
+UpgradeLog*.XML
+UpgradeLog*.htm
+# SQL Server files
+*.mdf
+*.ldf
+# Business Intelligence projects
+*.rdl.data
+*.bim.layout
+*.bim_*.settings
+# Microsoft Fakes
+FakesAssemblies/
+*.suo
+*.vcxproj.filters
+*.npp
+CMakeFiles/*
+nbproject/*
+*.cd
+*.cd
+a.out
+cmake-build-debug/*

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/CMakeLists.txt
----------------------------------------------------------------------
diff --git a/thirdparty/date/CMakeLists.txt b/thirdparty/date/CMakeLists.txt
new file mode 100644
index 0000000..683ddce
--- /dev/null
+++ b/thirdparty/date/CMakeLists.txt
@@ -0,0 +1,164 @@
+cmake_minimum_required( VERSION 3.1.0 )
+
+project( date_prj )
+
+include( GNUInstallDirs )
+
+find_package( Threads REQUIRED )
+
+# Override by setting on CMake command line.
+set( CMAKE_CXX_STANDARD 14 CACHE STRING "The C++ standard whose features are 
requested.")
+
+option( USE_SYSTEM_TZ_DB "Use the operating system's timezone database" OFF )
+option( USE_TZ_DB_IN_DOT "Save the timezone database in the current folder" 
OFF )
+option( BUILD_SHARED_LIBS  "Build a shared version of library" OFF )
+option( ENABLE_DATE_TESTING "Enable unit tests" ON )
+
+function( print_option OPT )
+       if ( NOT DEFINED PRINT_OPTION_CURR_${OPT} OR ( NOT 
PRINT_OPTION_CURR_${OPT} STREQUAL ${OPT} ) )
+               set( PRINT_OPTION_CURR_${OPT} ${${OPT}} CACHE BOOL "" )
+               mark_as_advanced(PRINT_OPTION_CURR_${OPT})
+               message( "# date: ${OPT} ${${OPT}}" )
+       endif( )
+endfunction( )
+
+print_option( USE_SYSTEM_TZ_DB )
+print_option( USE_TZ_DB_IN_DOT )
+print_option( BUILD_SHARED_LIBS  )
+print_option( ENABLE_DATE_TESTING )
+
+set( HEADER_FOLDER "include" )
+set( SOURCE_FOLDER "src" )
+set( TEST_FOLDER "test" )
+
+# This is needed so IDE's live MSVC show header files
+set( HEADER_FILES
+       ${HEADER_FOLDER}/date/chrono_io.h
+       ${HEADER_FOLDER}/date/date.h
+       ${HEADER_FOLDER}/date/ios.h
+       ${HEADER_FOLDER}/date/islamic.h
+       ${HEADER_FOLDER}/date/iso_week.h
+       ${HEADER_FOLDER}/date/julian.h
+       ${HEADER_FOLDER}/date/tz.h
+       ${HEADER_FOLDER}/date/tz_private.h
+)
+
+add_library( tz ${HEADER_FILES} ${SOURCE_FOLDER}/tz.cpp )
+
+if( USE_SYSTEM_TZ_DB )
+       target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=0 )
+       target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=0 )
+       # cannot set USE_OS_TZDB to 1 on Windows
+       if( NOT WIN32 )
+               target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=1 )
+       endif( )
+else( )
+       target_compile_definitions( tz PRIVATE -DUSE_AUTOLOAD=1 )
+       target_compile_definitions( tz PRIVATE -DHAS_REMOTE_API=1 )
+       target_compile_definitions( tz PUBLIC -DUSE_OS_TZDB=0 )
+       find_package( CURL REQUIRED )
+       include_directories( SYSTEM ${CURL_INCLUDE_DIRS} )
+       set( OPTIONAL_LIBRARIES ${CURL_LIBRARIES} )
+endif( )
+
+if( USE_TZ_DB_IN_DOT )
+       target_compile_definitions( tz PRIVATE -DINSTALL=. )
+endif( )
+
+target_link_libraries( tz ${CMAKE_THREAD_LIBS_INIT} ${OPTIONAL_LIBRARIES} )
+
+# add include folders to the library and targets that consume it
+target_include_directories(tz PUBLIC
+    $<BUILD_INTERFACE:
+        ${CMAKE_CURRENT_SOURCE_DIR}/${HEADER_FOLDER}
+    >
+    $<INSTALL_INTERFACE:
+        include
+    >
+)
+
+add_library(date_interface INTERFACE) # an interface (not a library), to 
enable automatic include_directory (for when just date.h, but not "tz.h and its 
lib" are needed)
+
+# add include folders to the INTERFACE and targets that consume it
+target_include_directories(date_interface INTERFACE
+    "$<BUILD_INTERFACE:${CMAKE_CURRENT_SOURCE_DIR}/include>"
+    $<INSTALL_INTERFACE:include>
+)
+
+if(WIN32 AND NOT CYGWIN)
+    set(DEF_INSTALL_CMAKE_DIR CMake)
+else()
+    set(DEF_INSTALL_CMAKE_DIR ${CMAKE_INSTALL_LIBDIR}/cmake/date)
+endif()
+
+install( TARGETS date_interface EXPORT dateConfig )
+install( EXPORT dateConfig DESTINATION ${DEF_INSTALL_CMAKE_DIR} )
+install( TARGETS tz
+       ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR}
+       LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}
+       RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR})  # This is for Windows
+install( DIRECTORY ${HEADER_FOLDER}/ DESTINATION include/ )
+
+if ( ENABLE_DATE_TESTING )
+
+    enable_testing( )
+
+    add_custom_target( testit COMMAND ${CMAKE_CTEST_COMMAND} )
+
+    add_dependencies( testit tz )
+    function( add_pass_tests TEST_GLOB TEST_PREFIX )
+        file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
+        include_directories( "${HEADER_FOLDER}/date" )
+
+        foreach( TEST_FILE ${FILENAMES} )
+            get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
+            get_filename_component( TEST_EXT ${TEST_FILE} EXT )
+            if( NOT ${TEST_EXT} STREQUAL ".fail.cpp" )
+                set( PREFIX "${TEST_PREFIX}_pass_${TEST_NAME}" )
+                set( BIN_NAME ${PREFIX}_bin )
+                set( TST_NAME ${PREFIX}_test )
+                add_executable( ${BIN_NAME} EXCLUDE_FROM_ALL ${TEST_FILE} )
+                add_test( ${TST_NAME} ${BIN_NAME} )
+                target_link_libraries( ${BIN_NAME} tz )
+                add_dependencies( testit ${BIN_NAME} )
+            endif( )
+        endforeach( )
+    endfunction( )
+
+    function( add_fail_tests TEST_GLOB TEST_PREFIX )
+        file( GLOB_RECURSE FILENAMES ${TEST_GLOB} )
+
+        foreach( TEST_FILE ${FILENAMES} )
+            get_filename_component( TEST_NAME ${TEST_FILE} NAME_WE )
+            get_filename_component( TEST_EXT ${TEST_FILE} EXT )
+
+                set( TEST_TYPE "_fail" )
+
+            set( PREFIX "${TEST_PREFIX}_fail_${TEST_NAME}" )
+            set( BIN_NAME ${PREFIX}_bin )
+            set( TST_NAME ${PREFIX}_test )
+
+            #target_compile_definitions( ${BIN_NAME} PRIVATE ${TST_NAME} )
+            set( TEST_BIN_NAME ${CMAKE_BINARY_DIR}/${BIN_NAME} )
+            add_custom_target( ${BIN_NAME}
+                COMMAND ${PROJECT_SOURCE_DIR}/compile_fail.sh ${TEST_BIN_NAME} 
${CMAKE_CXX_COMPILER} -std=c++14 -L${CMAKE_BINARY_DIR}/ -ltz 
-I${PROJECT_SOURCE_DIR}/${HEADER_FOLDER}/date -o ${BIN_NAME} ${TEST_FILE}
+                WORKING_DIRECTORY ${CMAKE_BINARY_DIR}
+                COMMENT ${TST_NAME}
+                )
+            add_test( ${TST_NAME} "${PROJECT_SOURCE_DIR}/test_fail.sh" 
${CMAKE_BINARY_DIR}/${BIN_NAME} WORKING_DIRECTORY "${PROJECT_SOURCE_DIR}/" )
+            #set_tests_properties( ${TST_NAME} PROPERTIES WILL_FAIL TRUE)
+            add_dependencies( testit ${BIN_NAME} )
+        endforeach( )
+    endfunction( )
+
+    file( GLOB children RELATIVE "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}" 
"${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/*" )
+    foreach( child ${children} )
+        if( IS_DIRECTORY "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/${child}" )
+            set( CUR_FOLDER "${PROJECT_SOURCE_DIR}/${TEST_FOLDER}/${child}" )
+            add_pass_tests( "${CUR_FOLDER}/*.cpp" ${child} )
+            if( NOT WIN32 )
+                add_fail_tests( "${CUR_FOLDER}/*.fail.cpp" ${child} )
+            endif( )
+        endif( )
+    endforeach( )
+endif( )

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/LICENSE.txt
----------------------------------------------------------------------
diff --git a/thirdparty/date/LICENSE.txt b/thirdparty/date/LICENSE.txt
new file mode 100644
index 0000000..79ea069
--- /dev/null
+++ b/thirdparty/date/LICENSE.txt
@@ -0,0 +1,31 @@
+The source code in this project is released using the MIT License. There is no
+global license for the project because each file is licensed individually with
+different author names and/or dates.
+
+If you contribute to this project, please add your name to the license of each
+file you modify.  If you have already contributed to this project and forgot to
+add your name to the license, please feel free to submit a new P/R to add your
+name to the license in each file you modified.
+
+For convenience, here is a copy of the MIT license found in each file except
+without author names or dates:
+
+The MIT License (MIT)
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/README.md
----------------------------------------------------------------------
diff --git a/thirdparty/date/README.md b/thirdparty/date/README.md
new file mode 100644
index 0000000..580d20d
--- /dev/null
+++ b/thirdparty/date/README.md
@@ -0,0 +1,58 @@
+# Date
+
+[![Join the chat at 
https://gitter.im/HowardHinnant/date](https://badges.gitter.im/HowardHinnant/date.svg)](https://gitter.im/HowardHinnant/date?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+---
+
+**[Try it out on wandbox!](https://wandbox.org/permlink/vqwMyTphHJv5iXX7)**
+
+## Summary
+
+This is actually several separate C++11/C++14/C++17 libraries:
+
+1. `"date.h"` is a header-only library which builds upon `<chrono>`.  It adds 
some new `duration` types, and new `time_point` types.  It also adds "field" 
types such as `year_month_day` which is a struct `{year, month, day}`.  And it 
provides convenient means to convert between the "field" types and the 
`time_point` types.
+
+    * Documentation: http://howardhinnant.github.io/date/date.html
+    * Video: https://www.youtube.com/watch?v=tzyGjOm8AKo
+    * Slides: http://schd.ws/hosted_files/cppcon2015/43/hinnant_dates.pdf
+
+1. `"tz.h"` / `"tz.cpp"`  are a timezone library built on top of the 
`"date.h"` library.  This timezone library is a complete parser of the IANA 
timezone database.  It provides for an easy way to access all of the data in 
this database, using the types from `"date.h"` and `<chrono>`.  The IANA 
database also includes data on leap seconds, and this library provides 
utilities to compute with that information as well.
+
+    * Documentation: http://howardhinnant.github.io/date/tz.html
+    * Video: https://www.youtube.com/watch?v=Vwd3pduVGKY
+    * Slides: 
http://schd.ws/hosted_files/cppcon2016/0f/Welcome%20To%20The%20Time%20Zone%20-%20Howard%20Hinnant%20-%20CppCon%202016.pdf
+
+1. `"iso_week.h"` is a header-only library built on top of the `"date.h"` 
library which implements the ISO week date calendar.
+
+    * Documentation: http://howardhinnant.github.io/date/iso_week.html
+
+1. `"julian.h"` is a header-only library built on top of the `"date.h"` 
library which implements a proleptic Julian calendar which is fully 
interoperable with everything above.
+
+    * Documentation: http://howardhinnant.github.io/date/julian.html
+
+1. `"islamic.h"` is a header-only library built on top of the `"date.h"` 
library which implements a proleptic Islamic calendar which is fully 
interoperable with everything above.
+
+    * Documentation: http://howardhinnant.github.io/date/islamic.html
+
+## Standardization
+
+Slightly modified versions of `"date.h"` and `"tz.h"` were voted into the 
C++20 working draft at the Jacksonville FL meeting on 2018-03-17:
+
+* http://howardhinnant.github.io/date/d0355r7.html
+
+## Build & Test
+
+You will need [CMake](https://cmake.org/) and a recent C++ compiler. Here 
follows a guide of how to build and test using the CMake Makefile generator.
+
+```bash
+mkdir build
+cd build
+cmake ../
+cmake --build . --target testit # Consider '-- -j4' for multithreading
+```
+## Projects using this library
+
+* www.safe.com
+* www.webtoolkit.eu/wt
+
+If you would like your project (or product) on this list, just let me know.

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/compile_fail.sh
----------------------------------------------------------------------
diff --git a/thirdparty/date/compile_fail.sh b/thirdparty/date/compile_fail.sh
new file mode 100755
index 0000000..60cf6b9
--- /dev/null
+++ b/thirdparty/date/compile_fail.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+export TEST_BIN_NAME=$1
+#echo "Building ${TEST_BIN_NAME}"
+shift 1
+export BUILD_COMMAND=$@
+#echo "Build command: ${BUILD_COMMAND}"
+eval ${BUILD_COMMAND} >/dev/null 2>/dev/null
+
+if [ $? -eq 0 ]; then
+       echo -ne "#!/bin/bash\nexit 1;" > ${TEST_BIN_NAME}
+else
+       echo -ne "#!/bin/bash\nexit 0;" > ${TEST_BIN_NAME}
+fi
+chmod u+x ${TEST_BIN_NAME}
+exit 0;
+

http://git-wip-us.apache.org/repos/asf/nifi-minifi-cpp/blob/8777ab5f/thirdparty/date/include/date/chrono_io.h
----------------------------------------------------------------------
diff --git a/thirdparty/date/include/date/chrono_io.h 
b/thirdparty/date/include/date/chrono_io.h
new file mode 100644
index 0000000..21be404
--- /dev/null
+++ b/thirdparty/date/include/date/chrono_io.h
@@ -0,0 +1,34 @@
+#ifndef CHRONO_IO_H
+#define CHRONO_IO_H
+
+// The MIT License (MIT)
+//
+// Copyright (c) 2016, 2017 Howard Hinnant
+//
+// Permission is hereby granted, free of charge, to any person obtaining a copy
+// of this software and associated documentation files (the "Software"), to 
deal
+// in the Software without restriction, including without limitation the rights
+// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+// copies of the Software, and to permit persons to whom the Software is
+// furnished to do so, subject to the following conditions:
+//
+// The above copyright notice and this permission notice shall be included in 
all
+// copies or substantial portions of the Software.
+//
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 
THE
+// SOFTWARE.
+//
+// Our apologies.  When the previous paragraph was written, lowercase had not 
yet
+// been invented (that would involve another several millennia of evolution).
+// We did not mean to shout.
+
+// This functionality has moved to "date.h"
+
+#include "date.h"
+
+#endif  // CHRONO_IO_H

Reply via email to