diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 00000000..01bf598c
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,512 @@
+root = true
+
+[*]
+charset = utf-8
+end_of_line = lf
+indent_size = 4
+indent_style = space
+insert_final_newline = false
+max_line_length = 120
+tab_width = 4
+ij_continuation_indent_size = 8
+ij_formatter_off_tag = @formatter:off
+ij_formatter_on_tag = @formatter:on
+ij_formatter_tags_enabled = true
+ij_smart_tabs = false
+ij_visual_guides =
+ij_wrap_on_typing = false
+
+[*.java]
+ij_java_align_consecutive_assignments = false
+ij_java_align_consecutive_variable_declarations = false
+ij_java_align_group_field_declarations = false
+ij_java_align_multiline_annotation_parameters = false
+ij_java_align_multiline_array_initializer_expression = false
+ij_java_align_multiline_assignment = false
+ij_java_align_multiline_binary_operation = false
+ij_java_align_multiline_chained_methods = false
+ij_java_align_multiline_deconstruction_list_components = true
+ij_java_align_multiline_extends_list = false
+ij_java_align_multiline_for = true
+ij_java_align_multiline_method_parentheses = false
+ij_java_align_multiline_parameters = true
+ij_java_align_multiline_parameters_in_calls = false
+ij_java_align_multiline_parenthesized_expression = false
+ij_java_align_multiline_records = true
+ij_java_align_multiline_resources = true
+ij_java_align_multiline_ternary_operation = false
+ij_java_align_multiline_text_blocks = false
+ij_java_align_multiline_throws_list = false
+ij_java_align_subsequent_simple_methods = false
+ij_java_align_throws_keyword = false
+ij_java_align_types_in_multi_catch = true
+ij_java_annotation_parameter_wrap = off
+ij_java_array_initializer_new_line_after_left_brace = false
+ij_java_array_initializer_right_brace_on_new_line = false
+ij_java_array_initializer_wrap = off
+ij_java_assert_statement_colon_on_next_line = false
+ij_java_assert_statement_wrap = off
+ij_java_assignment_wrap = off
+ij_java_binary_operation_sign_on_next_line = false
+ij_java_binary_operation_wrap = off
+ij_java_blank_lines_after_anonymous_class_header = 0
+ij_java_blank_lines_after_class_header = 0
+ij_java_blank_lines_after_imports = 1
+ij_java_blank_lines_after_package = 1
+ij_java_blank_lines_around_class = 1
+ij_java_blank_lines_around_field = 0
+ij_java_blank_lines_around_field_in_interface = 0
+ij_java_blank_lines_around_initializer = 1
+ij_java_blank_lines_around_method = 1
+ij_java_blank_lines_around_method_in_interface = 1
+ij_java_blank_lines_before_class_end = 0
+ij_java_blank_lines_before_imports = 1
+ij_java_blank_lines_before_method_body = 0
+ij_java_blank_lines_before_package = 0
+ij_java_block_brace_style = end_of_line
+ij_java_block_comment_add_space = false
+ij_java_block_comment_at_first_column = true
+ij_java_builder_methods =
+ij_java_call_parameters_new_line_after_left_paren = false
+ij_java_call_parameters_right_paren_on_new_line = false
+ij_java_call_parameters_wrap = off
+ij_java_case_statement_on_separate_line = true
+ij_java_catch_on_new_line = false
+ij_java_class_annotation_wrap = split_into_lines
+ij_java_class_brace_style = end_of_line
+ij_java_class_count_to_use_import_on_demand = 5
+ij_java_class_names_in_javadoc = 1
+ij_java_deconstruction_list_wrap = normal
+ij_java_do_not_indent_top_level_class_members = false
+ij_java_do_not_wrap_after_single_annotation = false
+ij_java_do_not_wrap_after_single_annotation_in_parameter = false
+ij_java_do_while_brace_force = never
+ij_java_doc_add_blank_line_after_description = true
+ij_java_doc_add_blank_line_after_param_comments = false
+ij_java_doc_add_blank_line_after_return = false
+ij_java_doc_add_p_tag_on_empty_lines = true
+ij_java_doc_align_exception_comments = true
+ij_java_doc_align_param_comments = true
+ij_java_doc_do_not_wrap_if_one_line = false
+ij_java_doc_enable_formatting = true
+ij_java_doc_enable_leading_asterisks = true
+ij_java_doc_indent_on_continuation = false
+ij_java_doc_keep_empty_lines = true
+ij_java_doc_keep_empty_parameter_tag = true
+ij_java_doc_keep_empty_return_tag = true
+ij_java_doc_keep_empty_throws_tag = true
+ij_java_doc_keep_invalid_tags = true
+ij_java_doc_param_description_on_new_line = false
+ij_java_doc_preserve_line_breaks = false
+ij_java_doc_use_throws_not_exception_tag = true
+ij_java_else_on_new_line = false
+ij_java_entity_dd_prefix =
+ij_java_entity_dd_suffix = EJB
+ij_java_entity_eb_prefix =
+ij_java_entity_eb_suffix = Bean
+ij_java_entity_hi_prefix =
+ij_java_entity_hi_suffix = Home
+ij_java_entity_lhi_prefix = Local
+ij_java_entity_lhi_suffix = Home
+ij_java_entity_li_prefix = Local
+ij_java_entity_li_suffix =
+ij_java_entity_pk_class = java.lang.String
+ij_java_entity_ri_prefix =
+ij_java_entity_ri_suffix =
+ij_java_entity_vo_prefix =
+ij_java_entity_vo_suffix = VO
+ij_java_enum_constants_wrap = off
+ij_java_extends_keyword_wrap = off
+ij_java_extends_list_wrap = off
+ij_java_field_annotation_wrap = split_into_lines
+ij_java_field_name_prefix =
+ij_java_field_name_suffix =
+ij_java_filter_class_prefix =
+ij_java_filter_class_suffix =
+ij_java_filter_dd_prefix =
+ij_java_filter_dd_suffix =
+ij_java_finally_on_new_line = false
+ij_java_for_brace_force = never
+ij_java_for_statement_new_line_after_left_paren = false
+ij_java_for_statement_right_paren_on_new_line = false
+ij_java_for_statement_wrap = off
+ij_java_generate_final_locals = false
+ij_java_generate_final_parameters = false
+ij_java_if_brace_force = never
+ij_java_imports_layout = *,|,javax.**,java.**,|,$*
+ij_java_indent_case_from_switch = true
+ij_java_insert_inner_class_imports = false
+ij_java_insert_override_annotation = true
+ij_java_keep_blank_lines_before_right_brace = 2
+ij_java_keep_blank_lines_between_package_declaration_and_header = 2
+ij_java_keep_blank_lines_in_code = 2
+ij_java_keep_blank_lines_in_declarations = 2
+ij_java_keep_builder_methods_indents = false
+ij_java_keep_control_statement_in_one_line = true
+ij_java_keep_first_column_comment = true
+ij_java_keep_indents_on_empty_lines = false
+ij_java_keep_line_breaks = true
+ij_java_keep_multiple_expressions_in_one_line = false
+ij_java_keep_simple_blocks_in_one_line = false
+ij_java_keep_simple_classes_in_one_line = false
+ij_java_keep_simple_lambdas_in_one_line = false
+ij_java_keep_simple_methods_in_one_line = false
+ij_java_label_indent_absolute = false
+ij_java_label_indent_size = 0
+ij_java_lambda_brace_style = end_of_line
+ij_java_layout_static_imports_separately = true
+ij_java_line_comment_add_space = false
+ij_java_line_comment_add_space_on_reformat = false
+ij_java_line_comment_at_first_column = true
+ij_java_listener_class_prefix =
+ij_java_listener_class_suffix =
+ij_java_local_variable_name_prefix =
+ij_java_local_variable_name_suffix =
+ij_java_message_dd_prefix =
+ij_java_message_dd_suffix = EJB
+ij_java_message_eb_prefix =
+ij_java_message_eb_suffix = Bean
+ij_java_method_annotation_wrap = split_into_lines
+ij_java_method_brace_style = end_of_line
+ij_java_method_call_chain_wrap = off
+ij_java_method_parameters_new_line_after_left_paren = false
+ij_java_method_parameters_right_paren_on_new_line = false
+ij_java_method_parameters_wrap = off
+ij_java_modifier_list_wrap = false
+ij_java_multi_catch_types_wrap = normal
+ij_java_names_count_to_use_import_on_demand = 3
+ij_java_new_line_after_lparen_in_annotation = false
+ij_java_new_line_after_lparen_in_deconstruction_pattern = true
+ij_java_new_line_after_lparen_in_record_header = false
+ij_java_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
+ij_java_parameter_annotation_wrap = off
+ij_java_parameter_name_prefix =
+ij_java_parameter_name_suffix =
+ij_java_parentheses_expression_new_line_after_left_paren = false
+ij_java_parentheses_expression_right_paren_on_new_line = false
+ij_java_place_assignment_sign_on_next_line = false
+ij_java_prefer_longer_names = true
+ij_java_prefer_parameters_wrap = false
+ij_java_record_components_wrap = normal
+ij_java_repeat_synchronized = true
+ij_java_replace_instanceof_and_cast = false
+ij_java_replace_null_check = true
+ij_java_replace_sum_lambda_with_method_ref = true
+ij_java_resource_list_new_line_after_left_paren = false
+ij_java_resource_list_right_paren_on_new_line = false
+ij_java_resource_list_wrap = off
+ij_java_rparen_on_new_line_in_annotation = false
+ij_java_rparen_on_new_line_in_deconstruction_pattern = true
+ij_java_rparen_on_new_line_in_record_header = false
+ij_java_servlet_class_prefix =
+ij_java_servlet_class_suffix =
+ij_java_servlet_dd_prefix =
+ij_java_servlet_dd_suffix =
+ij_java_session_dd_prefix =
+ij_java_session_dd_suffix = EJB
+ij_java_session_eb_prefix =
+ij_java_session_eb_suffix = Bean
+ij_java_session_hi_prefix =
+ij_java_session_hi_suffix = Home
+ij_java_session_lhi_prefix = Local
+ij_java_session_lhi_suffix = Home
+ij_java_session_li_prefix = Local
+ij_java_session_li_suffix =
+ij_java_session_ri_prefix =
+ij_java_session_ri_suffix =
+ij_java_session_si_prefix =
+ij_java_session_si_suffix = Service
+ij_java_space_after_closing_angle_bracket_in_type_argument = false
+ij_java_space_after_colon = true
+ij_java_space_after_comma = true
+ij_java_space_after_comma_in_type_arguments = true
+ij_java_space_after_for_semicolon = true
+ij_java_space_after_quest = true
+ij_java_space_after_type_cast = true
+ij_java_space_before_annotation_array_initializer_left_brace = false
+ij_java_space_before_annotation_parameter_list = false
+ij_java_space_before_array_initializer_left_brace = false
+ij_java_space_before_catch_keyword = true
+ij_java_space_before_catch_left_brace = true
+ij_java_space_before_catch_parentheses = true
+ij_java_space_before_class_left_brace = true
+ij_java_space_before_colon = true
+ij_java_space_before_colon_in_foreach = true
+ij_java_space_before_comma = false
+ij_java_space_before_deconstruction_list = false
+ij_java_space_before_do_left_brace = true
+ij_java_space_before_else_keyword = true
+ij_java_space_before_else_left_brace = true
+ij_java_space_before_finally_keyword = true
+ij_java_space_before_finally_left_brace = true
+ij_java_space_before_for_left_brace = true
+ij_java_space_before_for_parentheses = true
+ij_java_space_before_for_semicolon = false
+ij_java_space_before_if_left_brace = true
+ij_java_space_before_if_parentheses = true
+ij_java_space_before_method_call_parentheses = false
+ij_java_space_before_method_left_brace = true
+ij_java_space_before_method_parentheses = false
+ij_java_space_before_opening_angle_bracket_in_type_parameter = false
+ij_java_space_before_quest = true
+ij_java_space_before_switch_left_brace = true
+ij_java_space_before_switch_parentheses = true
+ij_java_space_before_synchronized_left_brace = true
+ij_java_space_before_synchronized_parentheses = true
+ij_java_space_before_try_left_brace = true
+ij_java_space_before_try_parentheses = true
+ij_java_space_before_type_parameter_list = false
+ij_java_space_before_while_keyword = true
+ij_java_space_before_while_left_brace = true
+ij_java_space_before_while_parentheses = true
+ij_java_space_inside_one_line_enum_braces = false
+ij_java_space_within_empty_array_initializer_braces = false
+ij_java_space_within_empty_method_call_parentheses = false
+ij_java_space_within_empty_method_parentheses = false
+ij_java_spaces_around_additive_operators = true
+ij_java_spaces_around_annotation_eq = true
+ij_java_spaces_around_assignment_operators = true
+ij_java_spaces_around_bitwise_operators = true
+ij_java_spaces_around_equality_operators = true
+ij_java_spaces_around_lambda_arrow = true
+ij_java_spaces_around_logical_operators = true
+ij_java_spaces_around_method_ref_dbl_colon = false
+ij_java_spaces_around_multiplicative_operators = true
+ij_java_spaces_around_relational_operators = true
+ij_java_spaces_around_shift_operators = true
+ij_java_spaces_around_type_bounds_in_type_parameters = true
+ij_java_spaces_around_unary_operator = false
+ij_java_spaces_within_angle_brackets = false
+ij_java_spaces_within_annotation_parentheses = false
+ij_java_spaces_within_array_initializer_braces = false
+ij_java_spaces_within_braces = false
+ij_java_spaces_within_brackets = false
+ij_java_spaces_within_cast_parentheses = false
+ij_java_spaces_within_catch_parentheses = false
+ij_java_spaces_within_deconstruction_list = false
+ij_java_spaces_within_for_parentheses = false
+ij_java_spaces_within_if_parentheses = false
+ij_java_spaces_within_method_call_parentheses = false
+ij_java_spaces_within_method_parentheses = false
+ij_java_spaces_within_parentheses = false
+ij_java_spaces_within_record_header = false
+ij_java_spaces_within_switch_parentheses = false
+ij_java_spaces_within_synchronized_parentheses = false
+ij_java_spaces_within_try_parentheses = false
+ij_java_spaces_within_while_parentheses = false
+ij_java_special_else_if_treatment = true
+ij_java_static_field_name_prefix =
+ij_java_static_field_name_suffix =
+ij_java_subclass_name_prefix =
+ij_java_subclass_name_suffix = Impl
+ij_java_ternary_operation_signs_on_next_line = false
+ij_java_ternary_operation_wrap = off
+ij_java_test_name_prefix =
+ij_java_test_name_suffix = Test
+ij_java_throws_keyword_wrap = off
+ij_java_throws_list_wrap = off
+ij_java_use_external_annotations = false
+ij_java_use_fq_class_names = false
+ij_java_use_relative_indents = false
+ij_java_use_single_class_imports = true
+ij_java_variable_annotation_wrap = off
+ij_java_visibility = public
+ij_java_while_brace_force = never
+ij_java_while_on_new_line = false
+ij_java_wrap_comments = false
+ij_java_wrap_first_method_in_call_chain = false
+ij_java_wrap_long_lines = false
+
+[{*.gant,*.groovy,*.gy,*.gradle}]
+ij_groovy_align_group_field_declarations = false
+ij_groovy_align_multiline_array_initializer_expression = false
+ij_groovy_align_multiline_assignment = false
+ij_groovy_align_multiline_binary_operation = false
+ij_groovy_align_multiline_chained_methods = false
+ij_groovy_align_multiline_extends_list = false
+ij_groovy_align_multiline_for = true
+ij_groovy_align_multiline_list_or_map = true
+ij_groovy_align_multiline_method_parentheses = false
+ij_groovy_align_multiline_parameters = true
+ij_groovy_align_multiline_parameters_in_calls = false
+ij_groovy_align_multiline_resources = true
+ij_groovy_align_multiline_ternary_operation = false
+ij_groovy_align_multiline_throws_list = false
+ij_groovy_align_named_args_in_map = true
+ij_groovy_align_throws_keyword = false
+ij_groovy_array_initializer_new_line_after_left_brace = false
+ij_groovy_array_initializer_right_brace_on_new_line = false
+ij_groovy_array_initializer_wrap = off
+ij_groovy_assert_statement_wrap = off
+ij_groovy_assignment_wrap = off
+ij_groovy_binary_operation_wrap = off
+ij_groovy_blank_lines_after_class_header = 0
+ij_groovy_blank_lines_after_imports = 1
+ij_groovy_blank_lines_after_package = 1
+ij_groovy_blank_lines_around_class = 1
+ij_groovy_blank_lines_around_field = 0
+ij_groovy_blank_lines_around_field_in_interface = 0
+ij_groovy_blank_lines_around_method = 1
+ij_groovy_blank_lines_around_method_in_interface = 1
+ij_groovy_blank_lines_before_imports = 1
+ij_groovy_blank_lines_before_method_body = 0
+ij_groovy_blank_lines_before_package = 0
+ij_groovy_block_brace_style = end_of_line
+ij_groovy_block_comment_add_space = false
+ij_groovy_block_comment_at_first_column = true
+ij_groovy_call_parameters_new_line_after_left_paren = false
+ij_groovy_call_parameters_right_paren_on_new_line = false
+ij_groovy_call_parameters_wrap = off
+ij_groovy_catch_on_new_line = false
+ij_groovy_class_annotation_wrap = split_into_lines
+ij_groovy_class_brace_style = end_of_line
+ij_groovy_class_count_to_use_import_on_demand = 5
+ij_groovy_do_while_brace_force = never
+ij_groovy_else_on_new_line = false
+ij_groovy_enable_groovydoc_formatting = true
+ij_groovy_enum_constants_wrap = off
+ij_groovy_extends_keyword_wrap = off
+ij_groovy_extends_list_wrap = off
+ij_groovy_field_annotation_wrap = split_into_lines
+ij_groovy_finally_on_new_line = false
+ij_groovy_for_brace_force = never
+ij_groovy_for_statement_new_line_after_left_paren = false
+ij_groovy_for_statement_right_paren_on_new_line = false
+ij_groovy_for_statement_wrap = off
+ij_groovy_ginq_general_clause_wrap_policy = 2
+ij_groovy_ginq_having_wrap_policy = 1
+ij_groovy_ginq_indent_having_clause = true
+ij_groovy_ginq_indent_on_clause = true
+ij_groovy_ginq_on_wrap_policy = 1
+ij_groovy_ginq_space_after_keyword = true
+ij_groovy_if_brace_force = never
+ij_groovy_import_annotation_wrap = 2
+ij_groovy_imports_layout = *,|,javax.**,java.**,|,$*
+ij_groovy_indent_case_from_switch = true
+ij_groovy_indent_label_blocks = true
+ij_groovy_insert_inner_class_imports = false
+ij_groovy_keep_blank_lines_before_right_brace = 2
+ij_groovy_keep_blank_lines_in_code = 2
+ij_groovy_keep_blank_lines_in_declarations = 2
+ij_groovy_keep_control_statement_in_one_line = true
+ij_groovy_keep_first_column_comment = true
+ij_groovy_keep_indents_on_empty_lines = false
+ij_groovy_keep_line_breaks = true
+ij_groovy_keep_multiple_expressions_in_one_line = false
+ij_groovy_keep_simple_blocks_in_one_line = false
+ij_groovy_keep_simple_classes_in_one_line = true
+ij_groovy_keep_simple_lambdas_in_one_line = true
+ij_groovy_keep_simple_methods_in_one_line = true
+ij_groovy_label_indent_absolute = false
+ij_groovy_label_indent_size = 0
+ij_groovy_lambda_brace_style = end_of_line
+ij_groovy_layout_static_imports_separately = true
+ij_groovy_line_comment_add_space = false
+ij_groovy_line_comment_add_space_on_reformat = false
+ij_groovy_line_comment_at_first_column = true
+ij_groovy_method_annotation_wrap = split_into_lines
+ij_groovy_method_brace_style = end_of_line
+ij_groovy_method_call_chain_wrap = off
+ij_groovy_method_parameters_new_line_after_left_paren = false
+ij_groovy_method_parameters_right_paren_on_new_line = false
+ij_groovy_method_parameters_wrap = off
+ij_groovy_modifier_list_wrap = false
+ij_groovy_names_count_to_use_import_on_demand = 3
+ij_groovy_packages_to_use_import_on_demand = java.awt.*,javax.swing.*
+ij_groovy_parameter_annotation_wrap = off
+ij_groovy_parentheses_expression_new_line_after_left_paren = false
+ij_groovy_parentheses_expression_right_paren_on_new_line = false
+ij_groovy_prefer_parameters_wrap = false
+ij_groovy_resource_list_new_line_after_left_paren = false
+ij_groovy_resource_list_right_paren_on_new_line = false
+ij_groovy_resource_list_wrap = off
+ij_groovy_space_after_assert_separator = true
+ij_groovy_space_after_colon = true
+ij_groovy_space_after_comma = true
+ij_groovy_space_after_comma_in_type_arguments = true
+ij_groovy_space_after_for_semicolon = true
+ij_groovy_space_after_quest = true
+ij_groovy_space_after_type_cast = true
+ij_groovy_space_before_annotation_parameter_list = false
+ij_groovy_space_before_array_initializer_left_brace = false
+ij_groovy_space_before_assert_separator = false
+ij_groovy_space_before_catch_keyword = true
+ij_groovy_space_before_catch_left_brace = true
+ij_groovy_space_before_catch_parentheses = true
+ij_groovy_space_before_class_left_brace = true
+ij_groovy_space_before_closure_left_brace = true
+ij_groovy_space_before_colon = true
+ij_groovy_space_before_comma = false
+ij_groovy_space_before_do_left_brace = true
+ij_groovy_space_before_else_keyword = true
+ij_groovy_space_before_else_left_brace = true
+ij_groovy_space_before_finally_keyword = true
+ij_groovy_space_before_finally_left_brace = true
+ij_groovy_space_before_for_left_brace = true
+ij_groovy_space_before_for_parentheses = true
+ij_groovy_space_before_for_semicolon = false
+ij_groovy_space_before_if_left_brace = true
+ij_groovy_space_before_if_parentheses = true
+ij_groovy_space_before_method_call_parentheses = false
+ij_groovy_space_before_method_left_brace = true
+ij_groovy_space_before_method_parentheses = false
+ij_groovy_space_before_quest = true
+ij_groovy_space_before_record_parentheses = false
+ij_groovy_space_before_switch_left_brace = true
+ij_groovy_space_before_switch_parentheses = true
+ij_groovy_space_before_synchronized_left_brace = true
+ij_groovy_space_before_synchronized_parentheses = true
+ij_groovy_space_before_try_left_brace = true
+ij_groovy_space_before_try_parentheses = true
+ij_groovy_space_before_while_keyword = true
+ij_groovy_space_before_while_left_brace = true
+ij_groovy_space_before_while_parentheses = true
+ij_groovy_space_in_named_argument = true
+ij_groovy_space_in_named_argument_before_colon = false
+ij_groovy_space_within_empty_array_initializer_braces = false
+ij_groovy_space_within_empty_method_call_parentheses = false
+ij_groovy_spaces_around_additive_operators = true
+ij_groovy_spaces_around_assignment_operators = true
+ij_groovy_spaces_around_bitwise_operators = true
+ij_groovy_spaces_around_equality_operators = true
+ij_groovy_spaces_around_lambda_arrow = true
+ij_groovy_spaces_around_logical_operators = true
+ij_groovy_spaces_around_multiplicative_operators = true
+ij_groovy_spaces_around_regex_operators = true
+ij_groovy_spaces_around_relational_operators = true
+ij_groovy_spaces_around_shift_operators = true
+ij_groovy_spaces_within_annotation_parentheses = false
+ij_groovy_spaces_within_array_initializer_braces = false
+ij_groovy_spaces_within_braces = true
+ij_groovy_spaces_within_brackets = false
+ij_groovy_spaces_within_cast_parentheses = false
+ij_groovy_spaces_within_catch_parentheses = false
+ij_groovy_spaces_within_for_parentheses = false
+ij_groovy_spaces_within_gstring_injection_braces = false
+ij_groovy_spaces_within_if_parentheses = false
+ij_groovy_spaces_within_list_or_map = false
+ij_groovy_spaces_within_method_call_parentheses = false
+ij_groovy_spaces_within_method_parentheses = false
+ij_groovy_spaces_within_parentheses = false
+ij_groovy_spaces_within_switch_parentheses = false
+ij_groovy_spaces_within_synchronized_parentheses = false
+ij_groovy_spaces_within_try_parentheses = false
+ij_groovy_spaces_within_tuple_expression = false
+ij_groovy_spaces_within_while_parentheses = false
+ij_groovy_special_else_if_treatment = true
+ij_groovy_ternary_operation_wrap = off
+ij_groovy_throws_keyword_wrap = off
+ij_groovy_throws_list_wrap = off
+ij_groovy_use_flying_geese_braces = false
+ij_groovy_use_fq_class_names = false
+ij_groovy_use_fq_class_names_in_javadoc = true
+ij_groovy_use_relative_indents = false
+ij_groovy_use_single_class_imports = true
+ij_groovy_variable_annotation_wrap = off
+ij_groovy_while_brace_force = never
+ij_groovy_while_on_new_line = false
+ij_groovy_wrap_chain_calls_after_dot = false
+ij_groovy_wrap_long_lines = false
+
+[{*.toml,Cargo.lock,Cargo.toml.orig,Gopkg.lock,Pipfile,poetry.lock}]
+ij_toml_keep_indents_on_empty_lines = false
diff --git a/.github/dependabot.yml b/.github/dependabot.yml
new file mode 100644
index 00000000..ee4fc95f
--- /dev/null
+++ b/.github/dependabot.yml
@@ -0,0 +1,9 @@
+version: 2
+updates:
+ - package-ecosystem: maven
+ directory: "/"
+ schedule:
+ interval: daily
+ open-pull-requests-limit: 10
+ labels:
+ - "dependencies"
diff --git a/.github/workflows/gradle-build.yml b/.github/workflows/gradle-build.yml
new file mode 100644
index 00000000..ed500900
--- /dev/null
+++ b/.github/workflows/gradle-build.yml
@@ -0,0 +1,28 @@
+name: Java CI with Gradle
+
+on:
+ push:
+ branches: [ main ]
+ pull_request:
+ branches: [ main ]
+
+permissions:
+ contents: write
+
+jobs:
+ build:
+ name: Java ${{ matrix.java_version }}
+ runs-on: ubuntu-latest
+ strategy:
+ fail-fast: false
+ matrix:
+ java_version: [ '17' ]
+ # java_version: ['8', '11', '17']
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v4
+ with:
+ java-version: ${{ matrix.java_version }}
+ distribution: 'temurin'
+ - name: Run a build
+ run: ./gradlew clean build --info
diff --git a/.github/workflows/publish-to-github-packages.yml b/.github/workflows/publish-to-github-packages.yml
new file mode 100644
index 00000000..93c5ad51
--- /dev/null
+++ b/.github/workflows/publish-to-github-packages.yml
@@ -0,0 +1,33 @@
+# This workflow uses actions that are not certified by GitHub.
+# They are provided by a third-party and are governed by
+# separate terms of service, privacy policy, and support
+# documentation.
+
+# GitHub recommends pinning actions to a commit SHA.
+# To get a newer version, you will need to update the SHA.
+# You can also reference a tag or branch, but the action may change without warning.
+
+name: Publish package to GitHub Packages
+on:
+ release:
+ types: [ created ]
+jobs:
+ publish:
+ runs-on: ubuntu-latest
+ permissions:
+ contents: read
+ packages: write
+ steps:
+ - uses: actions/checkout@v4
+ - uses: actions/setup-java@v3
+ with:
+ java-version: '17'
+ distribution: 'temurin'
+ - name: Validate Gradle wrapper
+ uses: gradle/wrapper-validation-action@ccb4328a959376b642e027874838f60f8e596de3
+ - name: Publish package
+ uses: gradle/gradle-build-action@749f47bda3e44aa060e82d7b3ef7e40d953bd629
+ with:
+ arguments: publish
+ env:
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
diff --git a/.gitignore b/.gitignore
index 8f3706cb..ae9e6e3e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,11 +1,16 @@
.classpath
.settings
.project
-.idea
+.gradle
workspace.xml
bin
target
-src/main/java/com/joestelmach/natty/generated/*
+build/
+src/main/java/org/natty/generated/*
src/main/java/*.tokens
-src/main/antlr3/com/joestelmach/natty/generated/DebugDateParser.g
-src/main/antlr3/com/joestelmach/natty/generated/DebugDateWalker.g
+src/main/antlr/org/natty/generated/DebugDateParser.g
+src/main/antlr/org/natty/generated/DebugDateWalker.g
+
+# IntelliJ Idea
+*.iml
+.idea
diff --git a/README b/README
deleted file mode 100644
index 69d4bdd0..00000000
--- a/README
+++ /dev/null
@@ -1,7 +0,0 @@
-Natty is a natural language date parser written in Java. Given a date
-expression, natty will apply standard language recognition and translation
-techniques to produce a list of corresponding dates with optional parse and
-syntax information.
-
-Complete documentation can be found here:
-http://natty.joestelmach.com
diff --git a/README.md b/README.md
new file mode 100644
index 00000000..cbfb5842
--- /dev/null
+++ b/README.md
@@ -0,0 +1,70 @@
+## What
+
+Natty is a natural language date parser written in Java. Given a date
+expression, natty will apply standard language recognition and translation
+techniques to produce a list of corresponding dates with optional parse and
+syntax information.
+
+## History
+
+Originally written by Joel Stelmach at https://github.com/joestelmach/natty and developed between 2010 and 2017.
+Abandoned since then.
+
+## Usage
+
+Maven:
+
+```
+
+ io.github.natty-parser
+ natty
+ 1.0.3
+
+```
+
+or [consult maven.org](https://search.maven.org/artifact/io.github.natty-parser/natty) for other build systems.
+
+## Idea behind the fork
+
+Started with [a thread in the original project](https://github.com/joestelmach/natty/issues/274). The aim is to try
+providing maintenance for the library.
+
+Plan / Priorities (as of November 2022):
+
+1. ~~Release version `1.0.0` with (possibly) the same code as the fork root, but under new name, consider renaming
+ packages and artifacts to use `natty-parser` as the moniker, etc.~~
+ DONE
+2. ~~Fix the tests (some are failing?).~~ DONE
+3. ~~Set up basic technicalities of the fork - Maven release process, CI (Continuous Integration), etc.~~ DONE
+4. Start accepting contributions (PRs), encourage the community to
+ solve [issues reported in the original repo](https://github.com/joestelmach/natty/issues)
+5. Consider switching to Gradle (as this is a build tool which is modern and I am familiar with)
+6. Decide on the overall vision of the project - at this point it's hard to tell, but I think a conscious decision on
+ what is gonna be supported would be
+ great - i.e. focus on i18n, customization, stability, or what?
+
+## Known issues from the parent project
+
+See [issues](issues.md)
+
+## Commitment
+
+I hope for open collaboration and contributions from others. To me it's totally a side-project, not the core activity.
+Yet, I can commit to being (fairly) responsive and inclusive.
+
+## Contibutions
+
+Are more than welcome. Feel free to reach out (e.g. by creating an issue in this repo) to offer your support and ideas.
+I am happy to include more
+maintainers. Tag @mccartney if no response for 2-3 days (I might have missed that).
+
+I see this project potentially being welcoming to many, incl. quite junior and inexperienced developers, who would like
+to learn and contribute.
+
+## Build
+
+Builds are done using the gradle wrapper. All that's need is a JDK (8 or upwards) to be installed on the machine.
+
+```shell
+./gradlew build
+```
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 00000000..be096dc1
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,87 @@
+plugins {
+ id 'java-library'
+ id 'maven-publish'
+ id 'antlr'
+
+ alias(libs.plugins.nebula.release)
+ alias(libs.plugins.lombok)
+}
+
+repositories {
+ mavenLocal()
+ maven {
+ url = uri('https://repo.maven.apache.org/maven2/')
+ }
+}
+
+dependencies {
+ api(
+ libs.antlr.runtime,
+ libs.ical4j,
+ libs.slf4j.api
+ )
+
+ antlr libs.antlr
+
+ testImplementation(
+ // libs.slf4j.log4j12, // required for Level
+ libs.junit,
+ libs.junit.jupiter.api,
+ libs.junit.jupiter.params,
+ libs.antlr.gunit,
+ libs.assertj.core
+ )
+ testRuntimeOnly(
+ // libs.slf4j.simple,
+ libs.log4j2,
+ libs.junit.jupiter.engine,
+ libs.junit.vintage.engine,
+ libs.junit.platform.engine,
+ //libs.logback.classic
+ )
+
+
+}
+
+description = 'Natty Date Parser'
+
+generateGrammarSource {
+
+ arguments += ["-visitor",
+ "-listener",
+ "-long-messages",
+ "-lib", "src/main/antlr/org/natty/generated/imports"
+ ]
+ outputDirectory = file("${project.buildDir}/generated-src/antlr/")
+ source "src/main/antlr"
+ include "org/natty/generated/DateLexer.g"
+ include "org/natty/generated/DateParser.g"
+
+}
+
+publishing {
+ publications {
+ maven(MavenPublication) {
+ from(components.java)
+ }
+ }
+}
+
+test {
+ useJUnitPlatform()
+ testLogging {
+ showStandardStreams = true
+ }
+}
+
+tasks.withType(JavaCompile).configureEach {
+ options.encoding = 'UTF-8'
+}
+
+tasks.withType(Javadoc).configureEach {
+ options.encoding = 'UTF-8'
+}
+
+tasks.compileJava {
+ dependsOn tasks.generateGrammarSource
+}
\ No newline at end of file
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 00000000..937b6c0f
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,5 @@
+group=io.github.natty-parser
+
+# nebula release settings
+release.scope=patch
+release.stage=SNAPSHOT
\ No newline at end of file
diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml
new file mode 100644
index 00000000..64afad62
--- /dev/null
+++ b/gradle/libs.versions.toml
@@ -0,0 +1,44 @@
+# This file was generated by the Gradle 'init' task.
+# https://docs.gradle.org/current/userguide/platforms.html#sub::toml-dependencies-format
+
+[versions]
+logback-classic = "1.3.14"
+log4j2 = "2.24.3"
+junit = "4.13.2"
+antlr = "3.5.3"
+ical4j = "3.2.14"
+slf4j = "2.0.17"
+junit-jupiter = "5.13.0"
+junit-platform = "1.13.0"
+assertj = "3.27.3"
+
+nebula-release = "19.0.10"
+lombok = "8.13.1"
+
+[libraries]
+logback-classic = { module = "ch.qos.logback:logback-classic", version.ref = "logback-classic" }
+log4j2 = { module = "org.apache.logging.log4j:log4j-slf4j2-impl", version.ref = "log4j2" }
+
+junit = { module = "junit:junit", version.ref = "junit" }
+antlr-runtime = { module = "org.antlr:antlr-runtime", version.ref = "antlr" }
+antlr = { module = "org.antlr:antlr", version.ref = "antlr" }
+antlr-gunit = { module = "org.antlr:gunit", version.ref = "antlr" }
+ical4j = { module = "org.mnode.ical4j:ical4j", version.ref = "ical4j" }
+slf4j-api = { module = "org.slf4j:slf4j-api", version.ref = "slf4j" }
+slf4j-log4j12 = { module = "org.slf4j:slf4j-log4j12", version.ref = "slf4j" }
+slf4j-simple = { module = "org.slf4j:slf4j-simple", version.ref = "slf4j" }
+junit-jupiter = { module = "org.junit.jupiter:junit-jupiter", version.ref = "junit-jupiter" }
+junit-jupiter-api = { module = "org.junit.jupiter:junit-jupiter-api", version.ref = "junit-jupiter" }
+junit-jupiter-params = { module = "org.junit.jupiter:junit-jupiter-params", version.ref = "junit-jupiter" }
+
+junit-jupiter-engine = { module = "org.junit.jupiter:junit-jupiter-engine", version.ref = "junit-jupiter" }
+junit-vintage-engine = { module = "org.junit.vintage:junit-vintage-engine", version.ref = "junit-jupiter" }
+# ... existing libraries ...
+assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" }
+junit-platform-engine = { module = "org.junit.platform:junit-platform-launcher", version.ref = "junit-platform" }
+
+
+
+[plugins]
+nebula-release = { id = "nebula.release", version.ref = "nebula-release" }
+lombok = { id = "io.freefair.lombok", version.ref = "lombok" }
\ No newline at end of file
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..d64cd491
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..002b867c
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.1-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
new file mode 100755
index 00000000..1aa94a42
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/issues.md b/issues.md
new file mode 100644
index 00000000..bf72ca1e
--- /dev/null
+++ b/issues.md
@@ -0,0 +1,196 @@
+# Issues from original repository
+as of 2022-05-08
+
+The issues are grouped into rough categories to make it possible to prioritise them a bit.
+
+## Crashes
+
+| ID | Title |
+|---------------------------------------------------------|-------------------------------------------------------------------------------------------------------------|
+| [#278](https://github.com/joestelmach/natty/issues/278) | 'last easter' gives NPE since 2021 |
+| [#277](https://github.com/joestelmach/natty/issues/277) | Cant parse this oddly specific string. |
+| [#263](https://github.com/joestelmach/natty/issues/263) | "Christma-eve" before 2000 throws NPE |
+| [#246](https://github.com/joestelmach/natty/issues/246) | Could not parse input org.antlr.runtime.EarlyExitException: null |
+| [#238](https://github.com/joestelmach/natty/issues/238) | natty line 1:23 no viable alternative at input '4' - Just override the emitErrorMessage method @joestelmach |
+| [#236](https://github.com/joestelmach/natty/issues/236) | java.lang.NullPointerException |
+| [#234](https://github.com/joestelmach/natty/issues/234) | NullPointerException |
+| [#193](https://github.com/joestelmach/natty/issues/193) | NumberFormatException |
+| [#190](https://github.com/joestelmach/natty/issues/190) | NullPointerExceptions |
+| [#162](https://github.com/joestelmach/natty/issues/162) | NPE / NumberFormatExceptions in WalkerState on Seasons and year seaks with miscalculated target year |
+| [#147](https://github.com/joestelmach/natty/issues/147) | NumberFormatException for "match-up on Saturday, February 22, 64-44, against Lynwood" |
+
+## Errors + Incorrect Parsing
+
+| ID | Title |
+|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
+| [#280](https://github.com/joestelmach/natty/issues/280) | Issues with multiple time points |
+| [#279](https://github.com/joestelmach/natty/issues/279) | Incorrectly parsing years as of Jan 1st, 2021 |
+| [#275](https://github.com/joestelmach/natty/issues/275) | Can't equate a month with 1 month |
+| [#273](https://github.com/joestelmach/natty/issues/273) | Can't parse due to milliseconds |
+| [#268](https://github.com/joestelmach/natty/issues/268) | Parser is failing because it doesn't detect date time |
+| [#267](https://github.com/joestelmach/natty/issues/267) | In free form text year expression in end is ignored |
+| [#266](https://github.com/joestelmach/natty/issues/266) | 19:40 Thursday (May 16, 2019) parsed wrongly |
+| [#244](https://github.com/joestelmach/natty/issues/244) | Wrong Date calculated for Days of the week |
+| [#243](https://github.com/joestelmach/natty/issues/243) | Can't parse month name on certain locations in text |
+| [#227](https://github.com/joestelmach/natty/issues/227) | Date is not identified |
+| [#211](https://github.com/joestelmach/natty/issues/211) | Please Correct "this month" result |
+| [#210](https://github.com/joestelmach/natty/issues/210) | Dates subsequent to "Weekend" are ignored by parser. |
+| [#207](https://github.com/joestelmach/natty/issues/207) | Year boundary condition on "before" |
+| [#206](https://github.com/joestelmach/natty/issues/206) | slight date issue |
+| [#203](https://github.com/joestelmach/natty/issues/203) | Past year interpretted |
+| [#202](https://github.com/joestelmach/natty/issues/202) | Not able to parse if text contains numeric date incorrect subscript |
+| [#201](https://github.com/joestelmach/natty/issues/201) | Midnight |
+| [#194](https://github.com/joestelmach/natty/issues/194) | Invalid parse of two consecutive dates |
+| [#192](https://github.com/joestelmach/natty/issues/192) | Natty parse string with no dates incorrectly |
+| [#189](https://github.com/joestelmach/natty/issues/189) | Inconsistent year parsing |
+| [#188](https://github.com/joestelmach/natty/issues/188) | Last week vs Last 1 week |
+| [#184](https://github.com/joestelmach/natty/issues/184) | yesterday afternoon at 2 |
+| [#180](https://github.com/joestelmach/natty/issues/180) | Doesn't seem to parse both times (as a range) |
+| [#171](https://github.com/joestelmach/natty/issues/171) | "End of this week", "till this week", "ends this week" are not working |
+| [#170](https://github.com/joestelmach/natty/issues/170) | Error with relative dates |
+| [#169](https://github.com/joestelmach/natty/issues/169) | Basic parsing is broken |
+| [#166](https://github.com/joestelmach/natty/issues/166) | "TEST123" gets parsed as HOURS_OF_DAY 3 |
+| [#161](https://github.com/joestelmach/natty/issues/161) | Date is detected in Url |
+| [#157](https://github.com/joestelmach/natty/issues/157) | doesnt parse |
+| [#155](https://github.com/joestelmach/natty/issues/155) | first monday of next leap year |
+| [#152](https://github.com/joestelmach/natty/issues/152) | Improper date format returned |
+| [#148](https://github.com/joestelmach/natty/issues/148) | In date ranges, tonight should imply the date (today's date), not just the time (8pm) |
+| [#146](https://github.com/joestelmach/natty/issues/146) | "In 2 weeks at 2pm" |
+| [#143](https://github.com/joestelmach/natty/issues/143) | Won't parse just the year |
+| [#142](https://github.com/joestelmach/natty/issues/142) | A minute ago |
+| [#139](https://github.com/joestelmach/natty/issues/139) | the vs. this |
+| [#137](https://github.com/joestelmach/natty/issues/137) | "First day of this year" returns current date |
+| [#119](https://github.com/joestelmach/natty/issues/119) | "A380 tomorrow" parses as 0 as explicit hour |
+| [#96](https://github.com/joestelmach/natty/issues/96) | "an hour ago" and "a minute ago" |
+| [#79](https://github.com/joestelmach/natty/issues/79) | "every week" unrecognised |
+| [#56](https://github.com/joestelmach/natty/issues/56) | Fails to parse when numbers that are greater than 99 AND divisible by 10 are used |
+| [#55](https://github.com/joestelmach/natty/issues/55) | "Before" clause seems not working |
+| [#54](https://github.com/joestelmach/natty/issues/54) | Natty parsing failed relative dates |
+| [#50](https://github.com/joestelmach/natty/issues/50) | Parsing error |
+
+## Format issues
+| ID | Title |
+|---------------------------------------------------------|--------------------------------------------------------------------------------|
+| [#271](https://github.com/joestelmach/natty/issues/271) | 9999-12-31 fails to parse |
+| [#265](https://github.com/joestelmach/natty/issues/265) | Date parsed wrongly |
+| [#260](https://github.com/joestelmach/natty/issues/260) | 04Oct17-31Oct17 |
+| [#257](https://github.com/joestelmach/natty/issues/257) | 02sep85 |
+| [#254](https://github.com/joestelmach/natty/issues/254) | Problem parsing Oct-07-2018 10:00 |
+| [#242](https://github.com/joestelmach/natty/issues/242) | Can't parse ddMMyyyy formate |
+| [#241](https://github.com/joestelmach/natty/issues/241) | Question/Issue, dates with no delimiters like 5Jan2018 are parsed in-correctly |
+| [#240](https://github.com/joestelmach/natty/issues/240) | Unable to parse "End of the Week" |
+| [#237](https://github.com/joestelmach/natty/issues/237) | Wrong parsing in case of % |
+| [#229](https://github.com/joestelmach/natty/issues/229) | Not able to parse boundary references |
+| [#228](https://github.com/joestelmach/natty/issues/228) | Not able to parse 4MAR17 |
+| [#215](https://github.com/joestelmach/natty/issues/215) | The first of the month |
+| [#214](https://github.com/joestelmach/natty/issues/214) | Unable to detect date in news article |
+| [#212](https://github.com/joestelmach/natty/issues/212) | Can't detect year when spelled out |
+| [#208](https://github.com/joestelmach/natty/issues/208) | Placing the year after time causes parsing to change the year |
+| [#204](https://github.com/joestelmach/natty/issues/204) | Natty is unable to parse this date |
+| [#179](https://github.com/joestelmach/natty/issues/179) | Only date is not being parsed |
+| [#167](https://github.com/joestelmach/natty/issues/167) | "2016.06.13 18:42:04" is parsed as "Fri Mar 25 20:16:06 UTC 2016" |
+| [#160](https://github.com/joestelmach/natty/issues/160) | @ between date and time |
+| [#158](https://github.com/joestelmach/natty/issues/158) | can't parse simple Datetype |
+| [#151](https://github.com/joestelmach/natty/issues/151) | no viable alternative at input '' |
+| [#144](https://github.com/joestelmach/natty/issues/144) | 15/12/2004 is not parsed correctly. |
+| [#118](https://github.com/joestelmach/natty/issues/118) | 29.01.57 is parsed incorrectly |
+| [#104](https://github.com/joestelmach/natty/issues/104) | date parsing |
+| [#75](https://github.com/joestelmach/natty/issues/75) | 20121028_161105.jpg |
+
+## Feature requests
+
+| ID | Title |
+|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
+| [#276](https://github.com/joestelmach/natty/issues/276) | Parsing of quarter not supported |
+| [#270](https://github.com/joestelmach/natty/issues/270) | support canonical timezone id (not just abbreviations) |
+| [#269](https://github.com/joestelmach/natty/issues/269) | Support for countries which use DD MM YYYY |
+| [#259](https://github.com/joestelmach/natty/issues/259) | Can't parse time fields like "60s" |
+| [#258](https://github.com/joestelmach/natty/issues/258) | Upgrade to Antlr4 |
+| [#256](https://github.com/joestelmach/natty/issues/256) | Year is added to current year 2018 jan 15 gives year 4036-01-01 3pm utc [other format] |
+| [#255](https://github.com/joestelmach/natty/issues/255) | Year references would be nice to match |
+| [#264](https://github.com/joestelmach/natty/issues/264) | "23rd" not getting parsed. Expected result is current_MM/23/current_YYYY |
+| [#249](https://github.com/joestelmach/natty/issues/249) | Is it possible to make natty multilingual? |
+| [#248](https://github.com/joestelmach/natty/issues/248) | Feature request |
+| [#245](https://github.com/joestelmach/natty/issues/245) | Feature Request: Set date format locale on call |
+| [#239](https://github.com/joestelmach/natty/issues/239) | A fortnight happens to be absent from Natty's vocabulary |
+| [#235](https://github.com/joestelmach/natty/issues/235) | java.lang.IllegalArgumentException: No enum constant com.joestelmach.natty.Holiday.INAUGURATION_DAY |
+| [#233](https://github.com/joestelmach/natty/issues/233) | Parsing week numbers |
+| [#231](https://github.com/joestelmach/natty/issues/231) | Couple days from now / next leap year |
+| [#226](https://github.com/joestelmach/natty/issues/226) | RFC 2822 Support |
+| [#223](https://github.com/joestelmach/natty/issues/223) | Add support for several languages |
+| [#222](https://github.com/joestelmach/natty/issues/222) | time period recognition |
+| [#221](https://github.com/joestelmach/natty/issues/221) | Add time grain for date parsed |
+| [#220](https://github.com/joestelmach/natty/issues/220) | Add support for "1h2m" format? |
+| [#216](https://github.com/joestelmach/natty/issues/216) | First Quarter / Q1-Q3 |
+| [#205](https://github.com/joestelmach/natty/issues/205) | Unable to distinguish time range |
+| [#200](https://github.com/joestelmach/natty/issues/200) | some day in the feature |
+| [#198](https://github.com/joestelmach/natty/issues/198) | 21st Oct last year is not supported |
+| [#197](https://github.com/joestelmach/natty/issues/197) | Not accepting the week after |
+| [#191](https://github.com/joestelmach/natty/issues/191) | "Mid August" parses to Aug. 01 |
+| [#187](https://github.com/joestelmach/natty/issues/187) | Unable to determine the following date type |
+| [#186](https://github.com/joestelmach/natty/issues/186) | Enhancement: Locale/Internationalization support? |
+| [#185](https://github.com/joestelmach/natty/issues/185) | Can't parse date from this :NT INT INST 2005 06 08 Let ECGD du 29 mars.pdf |
+| [#183](https://github.com/joestelmach/natty/issues/183) | quarter is not parsed |
+| [#182](https://github.com/joestelmach/natty/issues/182) | 25th of every month is not parsed |
+| [#181](https://github.com/joestelmach/natty/issues/181) | Can't parse short format: 3h ago |
+| [#177](https://github.com/joestelmach/natty/issues/177) | Doesn't recognize "Last quarter" |
+| [#172](https://github.com/joestelmach/natty/issues/172) | Does not recognize 'previous' keyword |
+| [#168](https://github.com/joestelmach/natty/issues/168) | Natty ignores milliseconds |
+| [#159](https://github.com/joestelmach/natty/issues/159) | parsing text with numbers |
+| [#153](https://github.com/joestelmach/natty/issues/153) | Date ranges? |
+| [#150](https://github.com/joestelmach/natty/issues/150) | "the beginning of (next) year" |
+| [#140](https://github.com/joestelmach/natty/issues/140) | recognize before month |
+| [#138](https://github.com/joestelmach/natty/issues/138) | Quarters |
+| [#134](https://github.com/joestelmach/natty/issues/134) | Incorrect parsing for dd-mm-yyyy and similar |
+| [#132](https://github.com/joestelmach/natty/issues/132) | Handle "Next Business Day" and "As Soon As Possible" |
+| [#129](https://github.com/joestelmach/natty/issues/129) | How to refer to beginning of (computer) time? |
+| [#123](https://github.com/joestelmach/natty/issues/123) | Parsing strings with only year information |
+| [#122](https://github.com/joestelmach/natty/issues/122) | How to translate natty recognition in other languages |
+| [#121](https://github.com/joestelmach/natty/issues/121) | prefixes "3 days from " doesn't seem to work |
+| [#120](https://github.com/joestelmach/natty/issues/120) | Date range doesn't take into account day of week |
+| [#114](https://github.com/joestelmach/natty/issues/114) | Relative dates with respect to another date rather than now |
+| [#110](https://github.com/joestelmach/natty/issues/110) | "JUNE 9TH - JUNE 23RD, 2014" is parsed as 06/09/201*5* - 06/23/2014 |
+| [#106](https://github.com/joestelmach/natty/issues/106) | how to parse twelve to ten? |
+| [#105](https://github.com/joestelmach/natty/issues/105) | java time zoneddatetime to string should be supported |
+| [#93](https://github.com/joestelmach/natty/issues/93) | need week end and work day aliases as we have for holidays |
+| [#80](https://github.com/joestelmach/natty/issues/80) | Four score and ten years ago |
+| [#77](https://github.com/joestelmach/natty/issues/77) | Recalculate a time- inferred date |
+| [#69](https://github.com/joestelmach/natty/issues/69) | Year bias... |
+| [#64](https://github.com/joestelmach/natty/issues/64) | How to parse dates of format DD/MM/YYYY? |
+| [#57](https://github.com/joestelmach/natty/issues/57) | Fails to parse day of month (eg: "the 21st") |
+| [#53](https://github.com/joestelmach/natty/issues/53) | Include possible date/time range ? |
+| [#48](https://github.com/joestelmach/natty/issues/48) | I18n support - different languages/countries |
+| [#47](https://github.com/joestelmach/natty/issues/47) | Make CalendarSource.setBaseDate an instance method |
+| [#44](https://github.com/joestelmach/natty/issues/44) | friendlier time rules |
+| [#41](https://github.com/joestelmach/natty/issues/41) | Feature: Future dates only option |
+| [#26](https://github.com/joestelmach/natty/issues/26) | Not Parsing "March 9-13, 2012" properly |
+| [#25](https://github.com/joestelmach/natty/issues/25) | can not parse "2011-09-12T13:55:00.004+02:00" |
+| [#23](https://github.com/joestelmach/natty/issues/23) | "each sunday in march" did not parse |
+| [#21](https://github.com/joestelmach/natty/issues/21) | French Dates Like 07-10-2011 |
+| [#20](https://github.com/joestelmach/natty/issues/20) | German Dates Like 07.10.2011 |
+| [#17](https://github.com/joestelmach/natty/issues/17) | Feature requests: More date ranges, custom event support |
+| [#16](https://github.com/joestelmach/natty/issues/16) | Cannot parse Sat., Sept. 24, 10:30 a.m.-9 p.m. format |
+| [#6](https://github.com/joestelmach/natty/issues/6) | Add time precision option |
+| [#3](https://github.com/joestelmach/natty/issues/3) | UK-formatted dates won't parse |
+
+## Misc
+
+| ID | Title |
+|---------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------|
+| [#281](https://github.com/joestelmach/natty/issues/281) | Documentation - 500 internal server error - http://natty.joestelmach.com/ |
+| [#274](https://github.com/joestelmach/natty/issues/274) | abandonware and forks diverge wildly |
+| [#253](https://github.com/joestelmach/natty/issues/253) | Runtime VerifyError: Verifier rejected class with Android <= 21 |
+| [#251](https://github.com/joestelmach/natty/issues/251) | Strange Memory Issue (leak) |
+| [#230](https://github.com/joestelmach/natty/issues/230) | Can't import project into android studio |
+| [#219](https://github.com/joestelmach/natty/issues/219) | How can I add a needed format? |
+| [#218](https://github.com/joestelmach/natty/issues/218) | Inferences could be more specific |
+| [#217](https://github.com/joestelmach/natty/issues/217) | Upgrade to ical4j 2.0 |
+| [#199](https://github.com/joestelmach/natty/issues/199) | how to get rid of: [main] INFO com.joestelmach.natty.Parser - STREAM |
+| [#195](https://github.com/joestelmach/natty/issues/195) | Getting date format from parser |
+| [#165](https://github.com/joestelmach/natty/issues/165) | Parser logs are too verbose at INFO |
+| [#156](https://github.com/joestelmach/natty/issues/156) | How do I mute console output? |
+| [#149](https://github.com/joestelmach/natty/issues/149) | Daylight savings logic? |
+| [#135](https://github.com/joestelmach/natty/issues/135) | SLF4J for class DateParser_NumericRules |
+| [#95](https://github.com/joestelmach/natty/issues/95) | Usage questions related to multiple groups/dates returned by parser |
+| [#84](https://github.com/joestelmach/natty/issues/84) | Javascript version? |
+| [#52](https://github.com/joestelmach/natty/issues/52) | Can i change in the java source code and create it's new jar without using maven and if no how can i do that using maven ? |
\ No newline at end of file
diff --git a/natty.iml b/natty.iml
deleted file mode 100644
index b8cf0290..00000000
--- a/natty.iml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
deleted file mode 100644
index c8db661e..00000000
--- a/pom.xml
+++ /dev/null
@@ -1,279 +0,0 @@
-
- 4.0.0
- com.joestelmach
- natty
- jar
- 0.14-SNAPSHOT
- Natty Date Parser
- natural language date parser
- http://natty.joestelmach.com
-
-
-
- MIT License
- LICENSE
-
-
-
-
- scm:git:git@github.com:joestelmach/natty.git
- scm:git:git@github.com:joestelmach/natty.git
- scm:git:git@github.com:joestelmach/natty.git
-
-
-
-
- joe
- Joe Stelmach
- joestelmach@gmail.com
- http://github.com/joestelmach
-
- developer
-
- -5
-
-
-
-
- ${basedir}/src/main/antlr3/com/joestelmach/natty/generated
- UTF-8
- UTF-8
- -Xdoclint:none
-
-
-
-
- sonatype-nexus-snapshots
- Sonatype Nexus Snapshots
- https://oss.sonatype.org/content/repositories/snapshots
-
-
-
- sonatype-nexus-staging
- Nexus Release Repository
- https://oss.sonatype.org/service/local/staging/deploy/maven2
-
-
-
-
-
-
-
-
- org.sonatype.plugins
- nexus-staging-maven-plugin
- 1.6.7
- true
-
- ossrh
- https://oss.sonatype.org/
- true
-
-
-
-
-
- org.apache.maven.plugins
- maven-release-plugin
- 2.0
-
- forked-path
-
-
-
-
-
- maven-compiler-plugin
- 2.3.2
-
- 1.6
- 1.6
-
-
-
-
-
- maven-clean-plugin
- 2.4.1
-
-
-
- src/main/java/com/joestelmach/natty/generated
-
- **/*.java
-
- false
-
-
-
-
-
-
-
- org.antlr
- antlr3-maven-plugin
- 3.5.2
-
-
-
- debug
-
- antlr
-
-
- true
- src/main/antlr3/com/joestelmach/natty/generated/imports
- src/main/java
-
- com/joestelmach/natty/generated/DateLexer.g
- com/joestelmach/natty/generated/DateParser.g
-
-
- com/joestelmach/natty/generated/imports/NumericRules.g
-
-
-
-
-
- non-debug
-
- antlr
-
-
- false
- src/main/java
- src/main/antlr3/com/joestelmach/natty/generated/imports
-
- com/joestelmach/natty/generated/DateLexer.g
- com/joestelmach/natty/generated/DateParser.g
- com/joestelmach/natty/generated/imports/NumericRules.g
-
-
-
-
-
-
-
-
-
- org.antlr
- maven-gunit-plugin
- 3.5.2
-
-
- maven-gunit-plugin
- test
-
- gunit
-
-
-
-
-
-
-
-
-
-
- release
-
-
- performRelease
- true
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-gpg-plugin
- 1.6
-
-
- sign-artifacts
- verify
-
- sign
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-javadoc-plugin
- 2.10.4
-
-
- attach-javadocs
-
- jar
-
-
-
-
-
-
-
- org.apache.maven.plugins
- maven-source-plugin
- 3.0.1
-
-
- attach-sources
-
- jar
-
-
-
-
-
-
-
-
-
-
-
-
- org.antlr
- antlr-runtime
- 3.5.2
-
-
-
- org.mnode.ical4j
- ical4j
- 1.0.2
-
-
-
- org.slf4j
- slf4j-api
- 1.7.10
-
-
-
- org.slf4j
- slf4j-log4j12
- 1.7.10
- test
-
-
-
- junit
- junit
- 4.1
- test
-
-
-
- org.antlr
- gunit
- 3.5.2
- test
-
-
-
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 00000000..1ae69cc3
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1 @@
+rootProject.name = 'natty'
diff --git a/src/main/antlr3/com/joestelmach/natty/generated/DateLexer.g b/src/main/antlr/org/natty/generated/DateLexer.g
similarity index 98%
rename from src/main/antlr3/com/joestelmach/natty/generated/DateLexer.g
rename to src/main/antlr/org/natty/generated/DateLexer.g
index 5f85fa30..1e2d06f4 100644
--- a/src/main/antlr3/com/joestelmach/natty/generated/DateLexer.g
+++ b/src/main/antlr/org/natty/generated/DateLexer.g
@@ -1,10 +1,10 @@
lexer grammar DateLexer;
-@header { package com.joestelmach.natty.generated; }
+@header { package org.natty.generated; }
@members {
private static org.slf4j.Logger _logger =
- org.slf4j.LoggerFactory.getLogger(com.joestelmach.natty.generated.DateLexer.class);
+ org.slf4j.LoggerFactory.getLogger(org.natty.generated.DateLexer.class);
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException re) {
diff --git a/src/main/antlr3/com/joestelmach/natty/generated/DateParser.g b/src/main/antlr/org/natty/generated/DateParser.g
similarity index 99%
rename from src/main/antlr3/com/joestelmach/natty/generated/DateParser.g
rename to src/main/antlr/org/natty/generated/DateParser.g
index d3c99128..a4addaa4 100644
--- a/src/main/antlr3/com/joestelmach/natty/generated/DateParser.g
+++ b/src/main/antlr/org/natty/generated/DateParser.g
@@ -37,12 +37,12 @@ tokens {
}
@header {
- package com.joestelmach.natty.generated;
+ package org.natty.generated;
}
@members {
private static org.slf4j.Logger _logger =
- org.slf4j.LoggerFactory.getLogger(com.joestelmach.natty.generated.DateParser.class);
+ org.slf4j.LoggerFactory.getLogger(org.natty.generated.DateParser.class);
@Override
public void displayRecognitionError(String[] tokenNames, RecognitionException re) {
diff --git a/src/main/antlr3/com/joestelmach/natty/generated/DateWalker.g b/src/main/antlr/org/natty/generated/DateWalker.g
similarity index 93%
rename from src/main/antlr3/com/joestelmach/natty/generated/DateWalker.g
rename to src/main/antlr/org/natty/generated/DateWalker.g
index 8d87db3b..0d198147 100644
--- a/src/main/antlr3/com/joestelmach/natty/generated/DateWalker.g
+++ b/src/main/antlr/org/natty/generated/DateWalker.g
@@ -5,10 +5,10 @@ options {
ASTLabelType=CommonTree;
}
-@header { package com.joestelmach.natty.generated; }
+@header { package org.natty.generated; }
@members {
- private com.joestelmach.natty.WalkerState _walkerState;
+ private org.natty.WalkerState _walkerState;
private java.util.Date referenceDate;
@Override
@@ -27,9 +27,9 @@ options {
this.referenceDate = referenceDate;
}
- public com.joestelmach.natty.WalkerState getState() {
+ public org.natty.WalkerState getState() {
if(_walkerState==null) {
- _walkerState = new com.joestelmach.natty.WalkerState(referenceDate);
+ _walkerState = new org.natty.WalkerState(referenceDate);
}
return _walkerState;
}
diff --git a/src/main/antlr3/com/joestelmach/natty/generated/TreeRewrite.g b/src/main/antlr/org/natty/generated/TreeRewrite.g
similarity index 96%
rename from src/main/antlr3/com/joestelmach/natty/generated/TreeRewrite.g
rename to src/main/antlr/org/natty/generated/TreeRewrite.g
index 4ca30869..f34be981 100644
--- a/src/main/antlr3/com/joestelmach/natty/generated/TreeRewrite.g
+++ b/src/main/antlr/org/natty/generated/TreeRewrite.g
@@ -7,7 +7,7 @@ options {
filter=true;
}
-@header { package com.joestelmach.natty.generated; }
+@header { package org.natty.generated; }
@members {
@Override
diff --git a/src/main/antlr3/com/joestelmach/natty/generated/imports/NumericRules.g b/src/main/antlr/org/natty/generated/imports/NumericRules.g
similarity index 100%
rename from src/main/antlr3/com/joestelmach/natty/generated/imports/NumericRules.g
rename to src/main/antlr/org/natty/generated/imports/NumericRules.g
diff --git a/src/main/java/com/joestelmach/natty/ANTLRNoCaseInputStream.java b/src/main/java/org/natty/ANTLRNoCaseInputStream.java
similarity index 95%
rename from src/main/java/com/joestelmach/natty/ANTLRNoCaseInputStream.java
rename to src/main/java/org/natty/ANTLRNoCaseInputStream.java
index 48448f75..30e86dcd 100644
--- a/src/main/java/com/joestelmach/natty/ANTLRNoCaseInputStream.java
+++ b/src/main/java/org/natty/ANTLRNoCaseInputStream.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import java.io.IOException;
import java.io.InputStream;
diff --git a/src/main/java/com/joestelmach/natty/CalendarSource.java b/src/main/java/org/natty/CalendarSource.java
similarity index 95%
rename from src/main/java/com/joestelmach/natty/CalendarSource.java
rename to src/main/java/org/natty/CalendarSource.java
index fea7a30b..bd89e44a 100644
--- a/src/main/java/com/joestelmach/natty/CalendarSource.java
+++ b/src/main/java/org/natty/CalendarSource.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import java.util.Date;
import java.util.GregorianCalendar;
diff --git a/src/main/java/com/joestelmach/natty/DateGroup.java b/src/main/java/org/natty/DateGroup.java
similarity index 98%
rename from src/main/java/com/joestelmach/natty/DateGroup.java
rename to src/main/java/org/natty/DateGroup.java
index 5adb99eb..87c8f90f 100644
--- a/src/main/java/com/joestelmach/natty/DateGroup.java
+++ b/src/main/java/org/natty/DateGroup.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import org.antlr.runtime.tree.Tree;
@@ -31,7 +31,7 @@ public DateGroup() {
/**
* Adds a date to this group
- * @param date
+ * @param date the date
*/
public void addDate(Date date) {
_dates.add(date);
@@ -77,7 +77,7 @@ public String getFullText() {
/**
* The line within the fullText this date group is found on
- * @return
+ * @return line number
*/
public int getLine() {
return _line;
diff --git a/src/main/java/com/joestelmach/natty/Holiday.java b/src/main/java/org/natty/Holiday.java
similarity index 97%
rename from src/main/java/com/joestelmach/natty/Holiday.java
rename to src/main/java/org/natty/Holiday.java
index fdb5414f..773a7b68 100644
--- a/src/main/java/com/joestelmach/natty/Holiday.java
+++ b/src/main/java/org/natty/Holiday.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import java.util.HashMap;
import java.util.Map;
diff --git a/src/main/java/com/joestelmach/natty/IcsSearcher.java b/src/main/java/org/natty/IcsSearcher.java
similarity index 99%
rename from src/main/java/com/joestelmach/natty/IcsSearcher.java
rename to src/main/java/org/natty/IcsSearcher.java
index ddf058d3..521fde3b 100644
--- a/src/main/java/com/joestelmach/natty/IcsSearcher.java
+++ b/src/main/java/org/natty/IcsSearcher.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import net.fortuna.ical4j.data.CalendarBuilder;
import net.fortuna.ical4j.data.ParserException;
diff --git a/src/main/java/com/joestelmach/natty/NattyTokenSource.java b/src/main/java/org/natty/NattyTokenSource.java
similarity index 95%
rename from src/main/java/com/joestelmach/natty/NattyTokenSource.java
rename to src/main/java/org/natty/NattyTokenSource.java
index cc69972f..3944e786 100644
--- a/src/main/java/com/joestelmach/natty/NattyTokenSource.java
+++ b/src/main/java/org/natty/NattyTokenSource.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import java.util.List;
diff --git a/src/main/java/com/joestelmach/natty/ParseListener.java b/src/main/java/org/natty/ParseListener.java
similarity index 98%
rename from src/main/java/com/joestelmach/natty/ParseListener.java
rename to src/main/java/org/natty/ParseListener.java
index 6784eb35..3a3b8454 100644
--- a/src/main/java/com/joestelmach/natty/ParseListener.java
+++ b/src/main/java/org/natty/ParseListener.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import org.antlr.runtime.RecognitionException;
import org.antlr.runtime.Token;
diff --git a/src/main/java/com/joestelmach/natty/ParseLocation.java b/src/main/java/org/natty/ParseLocation.java
similarity index 96%
rename from src/main/java/com/joestelmach/natty/ParseLocation.java
rename to src/main/java/org/natty/ParseLocation.java
index 3636d024..c69a042a 100644
--- a/src/main/java/com/joestelmach/natty/ParseLocation.java
+++ b/src/main/java/org/natty/ParseLocation.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
/**
* Represents an invocation of a parse rule
diff --git a/src/main/java/com/joestelmach/natty/Parser.java b/src/main/java/org/natty/Parser.java
similarity index 94%
rename from src/main/java/com/joestelmach/natty/Parser.java
rename to src/main/java/org/natty/Parser.java
index 9a0f666f..d05ae899 100644
--- a/src/main/java/com/joestelmach/natty/Parser.java
+++ b/src/main/java/org/natty/Parser.java
@@ -1,9 +1,9 @@
-package com.joestelmach.natty;
+package org.natty;
-import com.joestelmach.natty.generated.DateLexer;
-import com.joestelmach.natty.generated.DateParser;
-import com.joestelmach.natty.generated.DateWalker;
-import com.joestelmach.natty.generated.TreeRewrite;
+import org.natty.generated.DateLexer;
+import org.natty.generated.DateParser;
+import org.natty.generated.DateWalker;
+import org.natty.generated.TreeRewrite;
import org.antlr.runtime.*;
import org.antlr.runtime.tree.CommonTree;
import org.antlr.runtime.tree.CommonTreeNodeStream;
@@ -43,7 +43,7 @@ public class Parser {
/**
* Creates a new parser using the given time zone as the default
- * @param defaultTimeZone
+ * @param defaultTimeZone the timezone
*/
public Parser(TimeZone defaultTimeZone) {
_defaultTimeZone = defaultTimeZone;
@@ -57,11 +57,10 @@ public Parser() {
}
/**
- * Parses the given input value for one or more groups of
- * date alternatives
+ * Parses the given input value for one or more groups of date alternatives
*
- * @param value
- * @return
+ * @param value the date to parse
+ * @return list of date alternatives
*/
public List parse(String value) {
return parse(value, new Date());
@@ -72,9 +71,9 @@ public List parse(String value) {
* date alternatives with relative dates resolved according
* to referenceDate
*
- * @param value
- * @param referenceDate
- * @return
+ * @param value the date string to parse
+ * @param referenceDate the reference date for relative dates
+ * @return list of date alternatives
*/
public List parse(String value, Date referenceDate) {
@@ -204,7 +203,7 @@ private DateGroup singleParse(TokenStream stream, String fullText, Date referenc
// we only continue if a meaningful syntax tree has been built
if(tree.getChildCount() > 0) {
- _logger.info("PARSE: " + tokenString.toString());
+ _logger.debug("PARSE: {}", tokenString);
// rewrite the tree (temporary fix for http://www.antlr.org/jira/browse/ANTLR-427)
CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
@@ -218,7 +217,7 @@ private DateGroup singleParse(TokenStream stream, String fullText, Date referenc
walker.setReferenceDate(referenceDate);
walker.getState().setDefaultTimeZone(_defaultTimeZone);
walker.parse();
- _logger.info("AST: " + tree.toStringTree());
+ _logger.debug("AST: {}", tree.toStringTree());
// run through the results and append the parse information
group = walker.getState().getDateGroup();
@@ -307,7 +306,7 @@ private List collectTokenStreams(TokenStream stream) {
addGroup(currentGroup, groups);
}
- _logger.info("STREAM: " + tokenString.toString());
+ _logger.debug("STREAM: {}", tokenString);
List streams = new ArrayList();
for(List group:groups) {
if(!group.isEmpty()) {
@@ -316,7 +315,7 @@ private List collectTokenStreams(TokenStream stream) {
for (Token token : group) {
builder.append(DateParser.tokenNames[token.getType()]).append(" ");
}
- _logger.info(builder.toString());
+ _logger.debug(builder.toString());
streams.add(new CommonTokenStream(new NattyTokenSource(group)));
}
diff --git a/src/main/java/com/joestelmach/natty/Season.java b/src/main/java/org/natty/Season.java
similarity index 95%
rename from src/main/java/com/joestelmach/natty/Season.java
rename to src/main/java/org/natty/Season.java
index b0f5f8a9..3bc73bb7 100644
--- a/src/main/java/com/joestelmach/natty/Season.java
+++ b/src/main/java/org/natty/Season.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import java.util.HashMap;
import java.util.Map;
diff --git a/src/main/java/com/joestelmach/natty/WalkerState.java b/src/main/java/org/natty/WalkerState.java
similarity index 97%
rename from src/main/java/com/joestelmach/natty/WalkerState.java
rename to src/main/java/org/natty/WalkerState.java
index 58f29ee3..f69a6736 100644
--- a/src/main/java/com/joestelmach/natty/WalkerState.java
+++ b/src/main/java/org/natty/WalkerState.java
@@ -1,4 +1,4 @@
-package com.joestelmach.natty;
+package org.natty;
import java.util.*;
@@ -63,8 +63,8 @@ public void setDefaultTimeZone(final TimeZone zone) {
* seeks to a specified day of the week in the past or future.
*
* @param direction the direction to seek: two possibilities
- * '<' go backward
- * '>' go forward
+ * '<' go backward
+ * '>' go forward
*
* @param seekType the type of seek to perform (by_day or by_week)
* by_day means we seek to the very next occurrence of the given day
@@ -142,8 +142,8 @@ public void seekToDayOfYear(String dayOfYear) {
}
/**
- *
- * @param year
+ * Seek to the given year
+ * @param year the year to seek to.
*/
public void seekToYear(String year) {
int yearInt = Integer.parseInt(year);
@@ -158,8 +158,8 @@ public void seekToYear(String year) {
* seeks to a particular month
*
* @param direction the direction to seek: two possibilities
- * '<' go backward
- * '>' go forward
+ * '<' go backward
+ * '>' go forward
*
* @param seekAmount the amount to seek. Must be guaranteed to parse as an integer
*
@@ -197,12 +197,12 @@ public void seekToMonth(String direction, String seekAmount, String month) {
* seeks by a span of time (weeks, months, etc)
*
* @param direction the direction to seek: two possibilities
- * '<' go backward
- * '>' go forward
+ * '<' go backward
+ * '>' go forward
*
* @param seekAmount the amount to seek. Must be guaranteed to parse as an integer
*
- * @param span
+ * @param span the span to seek by, one of DAY, WEEK, MONTH, YEAR, HOUR, MINUTE, SECOND
*/
public void seekBySpan(String direction, String seekAmount, String span) {
if(span.startsWith(SEEK_PREFIX)) span = span.substring(3);
@@ -234,12 +234,7 @@ public void seekBySpan(String direction, String seekAmount, String span) {
null;
if(field > 0) _calendar.add(field, seekAmountInt * sign);
}
-
- /**
- *
- * @param index
- * @param dayOfWeek
- */
+
public void setDayOfWeekIndex(String index, String dayOfWeek) {
int indexInt = Integer.parseInt(index);
assert(indexInt > 0 && indexInt < 6);
@@ -314,7 +309,7 @@ else if(dayOfWeek != null) {
}
/**
- * Sets the the time of day
+ * Sets the time of day
*
* @param hours the hours to set. Must be guaranteed to parse as an
* integer between 0 and 23
@@ -395,9 +390,9 @@ public void seekToHoliday(String holidayString, String direction, String seekAmo
/**
* Seeks to the given holiday within the given year
- *
- * @param holidayString
- * @param yearString
+ * @see Holiday
+ * @param holidayString the name of the holiday as per Holiday enum
+ * @param yearString the year
*/
public void seekToHolidayYear(String holidayString, String yearString) {
Holiday holiday = Holiday.valueOf(holidayString);
@@ -423,8 +418,8 @@ public void seekToSeason(String seasonString, String direction, String seekAmoun
/**
* Seeks to the given season within the given year
*
- * @param seasonString
- * @param yearString
+ * @param seasonString The season to seek to
+ * @param yearString The year
*/
public void seekToSeasonYear(String seasonString, String yearString) {
Season season = Season.valueOf(seasonString);
diff --git a/src/test/gunit/DateLexer.testsuite b/src/test/gunit/DateLexer.testsuite
index 7ccea6a7..fa895a93 100644
--- a/src/test/gunit/DateLexer.testsuite
+++ b/src/test/gunit/DateLexer.testsuite
@@ -1,5 +1,5 @@
gunit Date;
-@header{package com.joestelmach.natty.generated;}
+@header{package org.natty.generated;}
JANUARY:
"january" OK
diff --git a/src/test/java/com/joestelmach/natty/AbstractTest.java b/src/test/java/com/joestelmach/natty/AbstractTest.java
deleted file mode 100644
index 34e235df..00000000
--- a/src/test/java/com/joestelmach/natty/AbstractTest.java
+++ /dev/null
@@ -1,163 +0,0 @@
-package com.joestelmach.natty;
-
-import org.junit.Assert;
-import org.junit.Before;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.Date;
-import java.util.List;
-
-/**
- *
- * @author Joe Stelmach
- */
-public abstract class AbstractTest {
- private static Calendar _calendar;
- protected static CalendarSource calendarSource;
- protected static Parser _parser;
-
-
- public static void initCalendarAndParser() {
- _calendar = Calendar.getInstance();
- _parser = new Parser();
- }
-
- /**
- * Resets the calendar source time before each test
- */
- @Before
- public void before() {
- calendarSource = new CalendarSource();
- }
-
- /**
- * Parses the given value into a collection of dates
- *
- * @param value
- * @return
- */
- protected List parseCollection(Date referenceDate, String value) {
- List dateGroup = _parser.parse(value, referenceDate);
- return dateGroup.isEmpty() ? new ArrayList() : dateGroup.get(0).getDates();
- }
-
- /**
- * Parses the given value, asserting that one and only one date is produced.
- *
- * @param value
- * @return
- */
- protected Date parseSingleDate(String value, Date referenceDate) {
- List dates = parseCollection(referenceDate, value);
- Assert.assertEquals(1, dates.size());
- return dates.get(0);
- }
-
- /**
- * Asserts that the given string value parses down to the given
- * month, day, and year values.
- *
- * @param value
- * @param month
- * @param day
- * @param year
- */
- protected void validateDate(Date referenceDate, String value, int month, int day, int year) {
- Date date = parseSingleDate(value, referenceDate);
- validateDate(date, month, day, year);
- }
-
- protected void validateDate(String value, int month, int day, int year) {
- validateDate(new Date(), value, month, day, year);
- }
-
- /**
- * Asserts that the given date contains the given attributes
- *
- * @param date
- * @param month
- * @param day
- * @param year
- */
- protected void validateDate(Date date, int month, int day, int year) {
- _calendar.setTime(date);
- Assert.assertEquals(month -1, _calendar.get(Calendar.MONTH));
- Assert.assertEquals(day, _calendar.get(Calendar.DAY_OF_MONTH));
- Assert.assertEquals(year, _calendar.get(Calendar.YEAR));
- }
-
- /**
- *
- * Asserts that the given string value parses down to the given
- * hours, minutes, and seconds
- *
- * @param value
- * @param hours
- * @param minutes
- * @param seconds
- */
- protected void validateTime(Date referenceDate, String value, int hours, int minutes, int seconds) {
- Date date = parseSingleDate(value, referenceDate);
- validateTime(date, hours, minutes, seconds);
- }
-
- /**
- *
- * Asserts that the given date contains the given time attributes
- *
- * @param date
- * @param hours
- * @param minutes
- * @param seconds
- */
- protected void validateTime(Date date, int hours, int minutes, int seconds) {
- _calendar.setTime(date);
- Assert.assertEquals(hours, _calendar.get(Calendar.HOUR_OF_DAY));
- Assert.assertEquals(minutes, _calendar.get(Calendar.MINUTE));
- Assert.assertEquals(seconds, _calendar.get(Calendar.SECOND));
- }
-
- /**
- *
- * Asserts that the given string value parses down to the given
- * month, day, year, hours, minutes, and seconds
- *
- * @param value
- * @param month
- * @param day
- * @param year
- * @param hours
- * @param minutes
- * @param seconds
- */
- protected void validateDateTime(Date referenceDate, String value, int month, int day, int year,
- int hours, int minutes, int seconds) {
-
- Date date = parseSingleDate(value, referenceDate);
- validateDateTime(date, month, day, year, hours, minutes, seconds);
- }
-
- /**
- * Asserts that the given date contains the given attributes
- *
- * @param date
- * @param month
- * @param day
- * @param year
- * @param hours
- * @param minutes
- * @param seconds
- */
- protected void validateDateTime(Date date, int month, int day, int year,
- int hours, int minutes, int seconds) {
-
- _calendar.setTime(date);
- Assert.assertEquals(month -1, _calendar.get(Calendar.MONTH));
- Assert.assertEquals(day, _calendar.get(Calendar.DAY_OF_MONTH));
- Assert.assertEquals(year, _calendar.get(Calendar.YEAR));
- Assert.assertEquals(hours, _calendar.get(Calendar.HOUR_OF_DAY));
- Assert.assertEquals(minutes, _calendar.get(Calendar.MINUTE));
- Assert.assertEquals(seconds, _calendar.get(Calendar.SECOND));
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/CPANTest.java b/src/test/java/com/joestelmach/natty/CPANTest.java
deleted file mode 100644
index c1081e5a..00000000
--- a/src/test/java/com/joestelmach/natty/CPANTest.java
+++ /dev/null
@@ -1,33 +0,0 @@
-package com.joestelmach.natty;
-
-import java.io.BufferedReader;
-import java.io.InputStreamReader;
-import java.util.List;
-
-import junit.framework.Assert;
-
-import org.junit.Test;
-
-/**
- *
- * @author Joe Stelmach
- */
-public class CPANTest {
-
- @Test
- public void sanityCheck() throws Exception {
- BufferedReader reader = new BufferedReader(new InputStreamReader(
- CPANTest.class.getResourceAsStream("/cpan.txt")));
- String value = null;
- while((value = reader.readLine()) != null) {
- if(!value.trim().startsWith("#") && value.trim().length() > 0) {
- Parser parser = new Parser();
- List groups = parser.parse(value);
- Assert.assertEquals(1, groups.size());
- Assert.assertTrue(groups.get(0).getDates().size() > 0);
- }
- }
-
- reader.close();
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/DateTest.java b/src/test/java/com/joestelmach/natty/DateTest.java
deleted file mode 100644
index c0152878..00000000
--- a/src/test/java/com/joestelmach/natty/DateTest.java
+++ /dev/null
@@ -1,406 +0,0 @@
-package com.joestelmach.natty;
-
-import junit.framework.Assert;
-import org.apache.log4j.Level;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.text.DateFormat;
-import java.util.*;
-import java.util.Map.Entry;
-
-/**
- * Runs the parser through the various date formats
- *
- * @author Joe Stelmach
- */
-public class DateTest extends AbstractTest {
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- @Test
- public void testFormal() {
- validateDate("1978-01-28", 1, 28, 1978);
- validateDate("2009-10-10", 10, 10, 2009);
- validateDate("1980-1-2", 1, 2, 1980);
- validateDate("12/12/12", 12, 12, 2012);
- validateDate("3/4", 3, 4, Calendar.getInstance().get(Calendar.YEAR));
- validateDate("sun, 11/21/2010", 11, 21, 2010);
- validateDate("in october 2006", 10, 1, 2006);
- validateDate("feb 1979", 2, 1, 1979);
- validateDate("jan '80", 1, 1, 1980);
- validateDate("2006-Jun-16", 6, 16, 2006);
- validateDate("28-Feb-2010", 2, 28, 2010);
- validateDate("9-Apr", 4, 9, Calendar.getInstance().get(Calendar.YEAR));
- validateDate("jan 10, '00", 1, 10, 2000);
- }
-
- @Test
- public void testRelaxed() {
- validateDate("oct 1, 1980", 10, 1, 1980);
- validateDate("oct. 1, 1980", 10, 1, 1980);
- validateDate("oct 1,1980", 10, 1, 1980);
- validateDate("1st oct in the year '89", 10, 1, 1989);
- validateDate("thirty first of december '80", 12, 31, 1980);
- validateDate("the first of december in the year 1980", 12, 1, 1980);
- validateDate("the 2 of february in the year 1980", 2, 2, 1980);
- validateDate("the 2nd of february in the year 1980", 2, 2, 1980);
- validateDate("the second of february in the year 1980", 2, 2, 1980);
- validateDate("jan. 2nd", 1, 2, Calendar.getInstance().get(Calendar.YEAR));
- validateDate("sun, nov 21 2010", 11, 21, 2010);
- validateDate("Second Monday in October 2017", 10, 9, 2017);
- validateDate("2nd thursday in sept. '02", 9, 12, 2002);
- }
-
- @Test
- public void testExplicitRelative() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/28/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "final thursday in april", 4, 28, 2011);
- validateDate(reference, "final thurs in sep", 9, 29, 2011);
- validateDate(reference, "4th february ", 2, 4, 2011);
- }
-
- @Test
- public void testRelative() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/28/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "yesterday", 2, 27, 2011);
- validateDate(reference, "tomorrow", 3, 1, 2011);
- validateDate(reference, "tmr", 3, 1, 2011);
- validateDate(reference, "in 3 days", 3, 3, 2011);
- validateDate(reference, "3 days ago", 2, 25, 2011);
- validateDate(reference, "in 3 weeks", 3, 21, 2011);
- validateDate(reference, "four weeks ago", 1, 31, 2011);
- validateDate(reference, "in 3 months", 5, 28, 2011);
- validateDate(reference, "three months ago", 11, 28, 2010);
- validateDate(reference, "in 3 years", 2, 28, 2014);
- validateDate(reference, "seven years ago", 2, 28, 2004);
- validateDate(reference, "60 years ago", 2, 28, 1951);
- validateDate(reference, "32 days ago", 1, 27, 2011);
- validateDate(reference, "320 days ago", 4, 14, 2010);
- validateDate(reference, "1200 days ago", 11, 16, 2007);
- validateDate(reference, "365 days from now", 2, 28, 2012);
- validateDate(reference, "100 months now", 6, 28, 2019);
- validateDate(reference, "100 years from now", 2, 28, 2111);
- validateDate(reference, "next monday", 3, 7, 2011);
- validateDate(reference, "next mon", 3, 7, 2011);
- validateDate(reference, "4 mondays from now", 3, 28, 2011);
- validateDate(reference, "4 mondays from today", 3, 28, 2011);
- validateDate(reference, "next weekend", 3, 12, 2011);
- validateDate(reference, "six mondays ago", 1, 17, 2011);
- validateDate(reference, "last monday", 2, 21, 2011);
- validateDate(reference, "last mon", 2, 21, 2011);
- validateDate(reference, "this past mon", 2, 21, 2011);
- validateDate(reference, "this coming mon", 3, 7, 2011);
- validateDate(reference, "this upcoming mon", 3, 7, 2011);
- validateDate(reference, "next thurs", 3, 10, 2011);
- validateDate(reference, "next month", 3, 28, 2011);
- validateDate(reference, "last month", 1, 28, 2011);
- validateDate(reference, "next week", 3, 7, 2011);
- validateDate(reference, "last week", 2, 21, 2011);
- validateDate(reference, "next year", 2, 28, 2012);
- validateDate(reference, "last year", 2, 28, 2010);
- validateDate(reference, "tues this week", 3, 1, 2011);
- validateDate(reference, "tuesday this week", 3, 1, 2011);
- validateDate(reference, "tuesday next week", 3, 8, 2011);
- validateDate(reference, "this september", 9, 1, 2011);
- validateDate(reference, "in a september", 9, 1, 2011);
- validateDate(reference, "in an october", 10, 1, 2011);
- validateDate(reference, "september", 9, 1, 2011);
- validateDate(reference, "last september", 9, 1, 2010);
- validateDate(reference, "next september", 9, 1, 2011);
- validateDate(reference, "january", 1, 1, 2011);
- validateDate(reference, "last january", 1, 1, 2011);
- validateDate(reference, "next january", 1, 1, 2012);
- validateDate(reference, "next february", 2, 1, 2012);
- validateDate(reference, "last february", 2, 1, 2010);
- validateDate(reference, "february ", 2, 1, 2011);
- validateDate(reference, "in a year", 2, 28, 2012);
- validateDate(reference, "in a week", 3, 7, 2011);
- validateDate(reference, "the saturday after next", 3, 19, 2011);
- validateDate(reference, "the monday after next", 3, 14, 2011);
- validateDate(reference, "the monday after next monday", 3, 14, 2011);
- validateDate(reference, "the monday before May 25", 5, 23, 2011);
- validateDate(reference, "the 2nd monday before May 25", 5, 16, 2011);
- validateDate(reference, "3 mondays after May 25", 6, 13, 2011);
- validateDate(reference, "tuesday before last", 2, 15, 2011);
- validateDate(reference, "a week from now", 3, 7, 2011);
- validateDate(reference, "a month from today", 3, 28, 2011);
- validateDate(reference, "a week after this friday", 3, 11, 2011);
- validateDate(reference, "a week from this friday", 3, 11, 2011);
- validateDate(reference, "two weeks from this friday", 3, 18, 2011);
- validateDate(reference, "the second week after this friday", 3, 18, 2011);
- validateDate(reference, "It's gonna snow! How about skiing tomorrow", 3, 1, 2011);
- validateDate(reference, "A week on tuesday", 3, 8, 2011);
- validateDate(reference, "A month ago", 1, 28, 2011);
- validateDate(reference, "A week ago", 2, 21, 2011);
- validateDate(reference, "A year ago", 2, 28, 2010);
- validateDate(reference, "this month", 2, 28, 2011);
- validateDate(reference, "current month", 2, 28, 2011);
- validateDate(reference, "current year", 2, 28, 2011);
- validateDate(reference, "first monday in 1 month", 3, 7, 2011);
- validateDate(reference, "first monday of month in 1 month", 3, 7, 2011);
- validateDate(reference, "first monday of 1 month", 3, 7, 2011);
- validateDate(reference, "first monday in 2 months", 4, 4, 2011);
- validateDate(reference, "first monday of 2 months", 4, 4, 2011);
- validateDate(reference, "first monday of month 2 months", 4, 4, 2011);
- validateDate(reference, "first monday of month in 2 months", 4, 4, 2011);
- validateDate(reference, "first monday in 3 months", 5, 2, 2011);
- validateDate(reference, "first monday of 3 months", 5, 2, 2011);
- validateDate(reference, "first monday of month in 3 months", 5, 2, 2011);
- validateDate(reference, "1 year 9 months from now", 11, 28, 2012);
- validateDate(reference, "1 year 9 months 1 day from now", 11, 29, 2012);
- validateDate(reference, "2 years 4 months ago", 10, 28, 2008);
- validateDate(reference, "2 years 4 months 5 days ago", 10, 23, 2008);
- }
-
- @Test
- public void testRange() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("1/02/2011");
- calendarSource = new CalendarSource(reference);
-
- List dates = parseCollection(reference, "monday to friday");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 3, 2011);
- validateDate(dates.get(1), 1, 7, 2011);
-
- dates = parseCollection(reference, "1999-12-31 to tomorrow");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 12, 31, 1999);
- validateDate(dates.get(1), 1, 3, 2011);
-
- dates = parseCollection(reference, "now to 2010-01-01");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 1, 1, 2010);
-
- dates = parseCollection(reference, "jan 1 to 2");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 1, 2011);
- validateDate(dates.get(1), 1, 2, 2011);
-
- dates = parseCollection(reference, "may 2nd to 5th");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 5, 2, 2011);
- validateDate(dates.get(1), 5, 5, 2011);
-
- dates = parseCollection(reference, "1/3 to 2/3");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 3, 2011);
- validateDate(dates.get(1), 2, 3, 2011);
-
- dates = parseCollection(reference, "2/3 to in one week");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 3, 2011);
- validateDate(dates.get(1), 1, 9, 2011);
-
- dates = parseCollection(reference, "first day of may to last day of may");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 5, 1, 2011);
- validateDate(dates.get(1), 5, 31, 2011);
-
- dates = parseCollection(reference, "feb 28th or 2 days after");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 28, 2011);
- validateDate(dates.get(1), 3, 2, 2011);
-
- dates = parseCollection(reference, "tomorrow at 10 and monday at 11");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 3, 2011);
- validateDate(dates.get(1), 1, 3, 2011);
-
- dates = parseCollection(reference, "tomorrow at 10 through tues at 11");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 3, 2011);
- validateDate(dates.get(1), 1, 4, 2011);
-
- dates = parseCollection(reference, "first day of 2009 to last day of 2009");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 1, 2009);
- validateDate(dates.get(1), 12, 31, 2009);
-
- dates = parseCollection(reference, "first to last day of 2008");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 1, 2008);
- validateDate(dates.get(1), 12, 31, 2008);
-
- dates = parseCollection(reference, "first to last day of september");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 9, 1, 2011);
- validateDate(dates.get(1), 9, 30, 2011);
-
- dates = parseCollection(reference, "first to last day of this september");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 9, 1, 2011);
- validateDate(dates.get(1), 9, 30, 2011);
-
- dates = parseCollection(reference, "first to last day of 2 septembers ago");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 9, 1, 2009);
- validateDate(dates.get(1), 9, 30, 2009);
-
- dates = parseCollection(reference, "first to last day of 2 septembers from now");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 9, 1, 2012);
- validateDate(dates.get(1), 9, 30, 2012);
-
- dates = parseCollection(reference, "for 5 days");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 1, 7, 2011);
-
- dates = parseCollection(reference, "for ten months");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 11, 2, 2011);
-
- dates = parseCollection(reference, "for twenty-five years");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 1, 2, 2036);
-
- dates = parseCollection(reference, "2 and 4 months");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 3, 2, 2011);
- validateDate(dates.get(1), 5, 2, 2011);
-
- dates = parseCollection(reference, "in 2 to 4 months");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 3, 2, 2011);
- validateDate(dates.get(1), 5, 2, 2011);
-
- dates = parseCollection(reference, "for 2 to 4 months");
- Assert.assertEquals(3, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 3, 2, 2011);
- validateDate(dates.get(2), 5, 2, 2011);
-
- dates = parseCollection(reference, "next 2 to 4 months");
- Assert.assertEquals(3, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 3, 2, 2011);
- validateDate(dates.get(2), 5, 2, 2011);
-
- dates = parseCollection(reference, "2 to 4 months from now");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 3, 2, 2011);
- validateDate(dates.get(1), 5, 2, 2011);
-
- dates = parseCollection(reference, "last 2 to 4 months");
- Assert.assertEquals(3, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 11, 2, 2010);
- validateDate(dates.get(2), 9, 2, 2010);
-
- dates = parseCollection(reference, "past 2 to 4 months");
- Assert.assertEquals(3, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 11, 2, 2010);
- validateDate(dates.get(2), 9, 2, 2010);
-
- dates = parseCollection(reference, "2 to 4 months ago");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 11, 2, 2010);
- validateDate(dates.get(1), 9, 2, 2010);
-
- dates = parseCollection(reference, "2 or 3 days ago");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 12, 31, 2010);
- validateDate(dates.get(1), 12, 30, 2010);
-
- dates = parseCollection(reference, "1 to 2 days");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 1, 3, 2011);
- validateDate(dates.get(1), 1, 4, 2011);
-
- dates = parseCollection(reference, "I want to go shopping in Knoxville, TN in the next five to six months.");
- Assert.assertEquals(3, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 6, 2, 2011);
- validateDate(dates.get(2), 7, 2, 2011);
-
- dates = parseCollection(reference, "I want to watch the fireworks in the next two to three months.");
- Assert.assertEquals(3, dates.size());
- validateDate(dates.get(0), 1, 2, 2011);
- validateDate(dates.get(1), 3, 2, 2011);
- validateDate(dates.get(2), 4, 2, 2011);
-
- dates = parseCollection(reference, "september 7th something");
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 7, 2011);
-
- dates = parseCollection(reference, "september 7th something happened here");
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 7, 2011);
-
- dates = parseCollection(reference, "bla bla bla 2 and 4 month");
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 3, 2, 2011);
- validateDate(dates.get(1), 5, 2, 2011);
- }
-
- // https://github.com/joestelmach/natty/issues/38
- @Test
- public void testRelativeDateDifferentTimezone() {
- // Prepare
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- Parser parser = new Parser(TimeZone.getTimeZone("US/Pacific"));
- // 2012, June 3, Sunday, 1 a.m. in US/Eastern GMT -4
- // Same time as
- // 2012, June 2, Saturday, 10 p.m. in US/Pacific GMT -7
- Calendar earlySunday = new GregorianCalendar(2012, 5, 3, 1, 0);
- calendarSource = new CalendarSource(earlySunday.getTime());
-
- // Run
- Date result = parser.parse("Sunday at 10am", earlySunday.getTime()).get(0).getDates().get(0);
-
- // Validate
- // Result should be June 3, 2012
- validateDate(result, 6, 3, 2012);
-
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- }
-
- public static void main(String[] args) {
-
- String value="easter '06";
-
- org.apache.log4j.Logger.getRootLogger().setLevel(Level.INFO);
-
- Parser parser = new Parser();
- List groups = parser.parse(value);
- for(DateGroup group:groups) {
- System.out.println(value);
- System.out.println(group.getSyntaxTree().toStringTree());
- System.out.println("line: " + group.getLine() + ", column: " + group.getPosition());
- System.out.println(group.getText());
- System.out.println(group.getDates());
- System.out.println("is time inferred: " + group.isTimeInferred());
- System.out.println("is recurring: " + group.isRecurring());
- System.out.println("recurs until: " + group.getRecursUntil());
-
- System.out.println("\n** Parse Locations **");
- for(Entry> entry:group.getParseLocations().entrySet()) {
- for(ParseLocation loc:entry.getValue()) {
- System.out.println(loc.getRuleName() + ": " + loc.getText());
- }
- }
-
- List conjunctionLocations = group.getParseLocations().get("conjunction");
- if(conjunctionLocations != null) {
- System.out.print("\nconjunctions: ");
- for(ParseLocation location:conjunctionLocations) {
- System.out.print(location.getText() + " ");
- }
- }
- System.out.print("\n\n");
- }
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/DateTimeTest.java b/src/test/java/com/joestelmach/natty/DateTimeTest.java
deleted file mode 100644
index e1f3570f..00000000
--- a/src/test/java/com/joestelmach/natty/DateTimeTest.java
+++ /dev/null
@@ -1,168 +0,0 @@
-package com.joestelmach.natty;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * Runs the parser through the various datetime formats
- *
- * @author Joe Stelmach
- */
-public class DateTimeTest extends AbstractTest {
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- @Test
- public void testSpecific() throws Exception {
- Date reference = DateFormat.getDateTimeInstance(DateFormat.SHORT,
- DateFormat.SHORT).parse("5/19/2012 12:00 am");
- calendarSource = new CalendarSource(reference);
-
- validateDateTime(reference, "1st oct in the year '89 1300 hours", 10, 1, 1989, 13, 0, 0);
- validateDateTime(reference, "1st oct in the year '89 at 1300 hours", 10, 1, 1989, 13, 0, 0);
- validateDateTime(reference, "1st oct in the year '89, 13:00", 10, 1, 1989, 13, 0, 0);
- validateDateTime(reference, "1st oct in the year '89,13:00", 10, 1, 1989, 13, 0, 0);
- validateDateTime(reference, "1st oct in the year '89, at 13:00", 10, 1, 1989, 13, 0, 0);
- validateDateTime(reference, "3am on oct 1st 2010", 10, 1, 2010, 3, 0, 0);
- validateDateTime(reference, "3am, october first 2010", 10, 1, 2010, 3, 0, 0);
- validateDateTime(reference, "3am,october first 2010", 10, 1, 2010, 3, 0, 0);
- validateDateTime(reference, "3am, on october first 2010", 10, 1, 2010, 3, 0, 0);
- validateDateTime(reference, "3am october first 2010", 10, 1, 2010, 3, 0, 0);
- validateDateTime(reference, "April 20, 10am", 4, 20, 2012, 10, 0, 0);
- validateDateTime(reference, "April 20 10", 4, 20, 2012, 10, 0, 0);
- validateDateTime(reference, "April 20 at 10 am", 4, 20, 2012, 10, 0, 0);
- validateDateTime(reference, "Mar 16, 2015 3:33:39 PM", 3, 16, 2015, 15, 33, 39);
- }
-
- @Test
- public void testRelative() throws Exception {
- Date reference = DateFormat.getDateTimeInstance(DateFormat.SHORT,
- DateFormat.SHORT).parse("2/24/2011 12:00 am");
- calendarSource = new CalendarSource(reference);
-
- validateDateTime(reference, "seven years ago at 3pm", 2, 24, 2004, 15, 0, 0);
- validateDateTime(reference, "next wed. at 5pm", 3, 2, 2011, 17, 0, 0);
- validateDateTime(reference, "3 days after next wed at 6a", 3, 5, 2011, 6, 0, 0);
- validateDateTime(reference, "8pm on the sunday after next wed", 3, 6, 2011, 20, 0, 0);
- validateDateTime(reference, "two days after today @ 6p", 2, 26, 2011, 18, 0, 0);
- validateDateTime(reference, "two days from today @ 6p", 2, 26, 2011, 18, 0, 0);
- validateDateTime(reference, "11:59 on 3 sundays after next wed", 3, 20, 2011, 11, 59, 0);
- validateDateTime(reference, "the day after next 6pm", 2, 26, 2011, 18, 0, 0);
- validateDateTime(reference, "the week after next 2a", 3, 10, 2011, 2, 0, 0);
- validateDateTime(reference, "the month after next 0700", 4, 24, 2011, 7, 0, 0);
- validateDateTime(reference, "the year after next @ midnight", 2, 24, 2013, 0, 0, 0);
- validateDateTime(reference, "wed of the week after next in the evening", 3, 9, 2011, 19, 0, 0);
- validateDateTime(reference, "the 28th of the month after next in the morning", 4, 28, 2011, 8, 0, 0);
- validateDateTime(reference, "this morning", 2, 24, 2011, 8, 0, 0);
- validateDateTime(reference, "this afternoon", 2, 24, 2011, 12, 0, 0);
- validateDateTime(reference, "this evening", 2, 24, 2011, 19, 0, 0);
- validateDateTime(reference, "today evening", 2, 24, 2011, 19, 0, 0);
- validateDateTime(reference, "tomorrow evening", 2, 25, 2011, 19, 0, 0);
- validateDateTime(reference, "friday evening", 2, 25, 2011, 19, 0, 0);
- validateDateTime(reference, "monday 6 in the morning", 2, 28, 2011, 6, 0, 0);
- validateDateTime(reference, "monday 4 in the afternoon", 2, 28, 2011, 16, 0, 0);
- validateDateTime(reference, "monday 9 in the evening", 2, 28, 2011, 21, 0, 0);
- validateDateTime(reference, "tomorrow @ noon", 2, 25, 2011, 12, 0, 0);
- validateDateTime(reference, "Acknowledged. Let's meet at 9pm.", 2, 24, 2011, 21, 0, 0);
- validateDateTime(reference, "tuesday,\u00A012:50 PM", 3, 1, 2011, 12, 50, 0);
- validateDateTime(reference, "tonight at 6:30", 2, 24, 2011, 18, 30, 0);
- validateDateTime(reference, "tonight at 6", 2, 24, 2011, 18, 0, 0);
- validateDateTime(reference, "tonight at 2", 2, 25, 2011, 2, 0, 0);
- validateDateTime(reference, "tonight at 4:59", 2, 25, 2011, 4, 59, 0);
- validateDateTime(reference, "tonight at 5", 2, 24, 2011, 17, 0, 0);
- validateDateTime(reference, "this evening at 5", 2, 24, 2011, 17, 0, 0);
- validateDateTime(reference, "this evening at 2", 2, 25, 2011, 2, 0, 0);
- validateDateTime(reference, "tomorrow evening at 5", 2, 25, 2011, 17, 0, 0);
- validateDateTime(reference, "wed evening at 8:30", 3, 2, 2011, 20, 30, 0);
- validateDateTime(reference, "750 minutes from now", 2, 24, 2011, 12, 30, 0);
- validateDateTime(reference, "1500 minutes from now", 2, 25, 2011, 1, 0, 0);
- }
-
- @Test
- public void testRange() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("6/12/2010");
- calendarSource = new CalendarSource(reference);
-
- List dates = parseCollection(reference, "2009-03-10 9:00 to 11:00");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 3, 10, 2009, 9, 0, 0);
- validateDateTime(dates.get(1), 3, 10, 2009, 11, 0, 0);
-
- dates = parseCollection(reference, "26 oct 10:00 am to 11:00 am");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 10, 26, 2010, 10, 0, 0);
- validateDateTime(dates.get(1), 10, 26, 2010, 11, 0, 0);
-
- dates = parseCollection(reference, "16:00 nov 6 to 17:00");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 11, 6, 2010, 16, 0, 0);
- validateDateTime(dates.get(1), 11, 6, 2010, 17, 0, 0);
-
- dates = parseCollection(reference, "6am dec 5 to 7am");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 12, 5, 2010, 6, 0, 0);
- validateDateTime(dates.get(1), 12, 5, 2010, 7, 0, 0);
-
- dates = parseCollection(reference, "3/3 21:00 to in 5 days");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 3, 3, 2010, 21, 0, 0);
- validateDateTime(dates.get(1), 6, 17, 2010, 21, 0, 0);
-
- dates = parseCollection(reference, "November 20 2 p.m. to 3 p.m");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 11, 20, 2010, 14, 0, 0);
- validateDateTime(dates.get(1), 11, 20, 2010, 15, 0, 0);
-
- dates = parseCollection(reference, "November 20 2 p.m. - 3 p.m.");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 11, 20, 2010, 14, 0, 0);
- validateDateTime(dates.get(1), 11, 20, 2010, 15, 0, 0);
- }
-
- @Test
- public void testList() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("05/19/2012");
- calendarSource = new CalendarSource(reference);
-
- List dates =
- parseCollection(reference, "June 25th at 9am and July 2nd at 10am and August 16th at 11am");
- Assert.assertEquals(3, dates.size());
- validateDateTime(dates.get(0), 6, 25, 2012, 9, 0, 0);
- validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
- validateDateTime(dates.get(2), 8, 16, 2012, 11, 0, 0);
-
- dates = parseCollection(reference, "June 25th at 10am and July 2nd and August 16th");
- Assert.assertEquals(3, dates.size());
- validateDateTime(dates.get(0), 6, 25, 2012, 10, 0, 0);
- validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
- validateDateTime(dates.get(2), 8, 16, 2012, 10, 0, 0);
-
- dates = parseCollection(reference, "June 25th and July 2nd at 10am and August 16th");
- Assert.assertEquals(3, dates.size());
- validateDateTime(dates.get(0), 6, 25, 2012, 10, 0, 0);
- validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
- validateDateTime(dates.get(2), 8, 16, 2012, 10, 0, 0);
-
- dates = parseCollection(reference, "June 25th and July 2nd and August 16th at 10am");
- Assert.assertEquals(3, dates.size());
- validateDateTime(dates.get(0), 6, 25, 2012, 10, 0, 0);
- validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
- validateDateTime(dates.get(2), 8, 16, 2012, 10, 0, 0);
-
- dates = parseCollection(reference, "slept from 3:30 a.m. To 9:41 a.m. On April 10th");
- Assert.assertEquals(2, dates.size());
- validateDateTime(dates.get(0), 4, 10, 2012, 3, 30, 0);
- validateDateTime(dates.get(1), 4, 10, 2012, 9, 41, 0);
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/IcsTest.java b/src/test/java/com/joestelmach/natty/IcsTest.java
deleted file mode 100644
index 48836955..00000000
--- a/src/test/java/com/joestelmach/natty/IcsTest.java
+++ /dev/null
@@ -1,153 +0,0 @@
-package com.joestelmach.natty;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-
-public class IcsTest extends AbstractTest {
-
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- @Test
- public void testUpcomingSeason() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("5/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "spring", 3, 20, 2012);
- validateDate(reference, "summer", 6, 21, 2011);
- validateDate(reference, "fall", 9, 23, 2011);
- validateDate(reference, "autumn", 9, 23, 2011);
- validateDate(reference, "winter", 12, 22, 2011);
- }
-
- @Test
- public void testUpcomingHoliday() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "april fool's day", 4, 1, 2012);
- validateDate(reference, "black friday", 11, 25, 2011);
- validateDate(reference, "christmas", 12, 25, 2011);
- validateDate(reference, "christmas eve", 12, 24, 2011);
- validateDate(reference, "columbus day", 10, 8, 2012);
- validateDate(reference, "earth day", 4, 22, 2012);
- validateDate(reference, "easter", 4, 8, 2012);
- validateDate(reference, "father's day", 6, 17, 2012);
- validateDate(reference, "flag day", 6, 14, 2012);
- validateDate(reference, "good friday", 4, 6, 2012);
- validateDate(reference, "groundhog day", 2, 2, 2012);
- validateDate(reference, "halloween", 10, 31, 2012);
- validateDate(reference, "independence day", 7, 4, 2012);
- validateDate(reference, "kwanzaa", 12, 26, 2011);
- validateDate(reference, "labor day", 9, 3, 2012);
- validateDate(reference, "mlk day", 1, 16, 2012);
- validateDate(reference, "memorial day", 5, 28, 2012);
- validateDate(reference, "mother's day", 5, 13, 2012);
- validateDate(reference, "new year's day", 1, 1, 2012);
- validateDate(reference, "new year's eve", 12, 31, 2011);
- validateDate(reference, "patriot day", 9, 11, 2012);
- validateDate(reference, "president's day", 2, 20, 2012);
- validateDate(reference, "st patty's day", 3, 17, 2012);
- validateDate(reference, "tax day", 4, 15, 2012);
- validateDate(reference, "thanksgiving", 11, 24, 2011);
- validateDate(reference, "election day", 11, 8, 2011);
- validateDate(reference, "valentine day", 2, 14, 2012);
- validateDate(reference, "veterans day", 11, 11, 2011);
- }
-
- @Test
- public void testRelativeHolidays() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "2 black fridays from now", 11, 23, 2012);
- validateDate(reference, "three memorial days ago", 5, 25, 2009);
- }
-
- @Test
- public void testSeasonsByYear() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "spring 2010", 3, 20, 2010);
- validateDate(reference, "spring 2018", 3, 20, 2018);
- validateDate(reference, "spring 1928", 3, 20, 1928);
-
- validateDate(reference, "summer 2012", 6, 20, 2012);
- validateDate(reference, "summer 2015", 6, 21, 2015);
- validateDate(reference, "summer 1960", 6, 21, 1960);
-
- validateDate(reference, "fall 2011", 9, 23, 2011);
- validateDate(reference, "fall 2012", 9, 22, 2012);
- validateDate(reference, "autumn 2016", 9, 22, 2016);
- validateDate(reference, "autumn 1800", 9, 23, 1800);
-
- validateDate(reference, "winter 2016", 12, 21, 2016);
- validateDate(reference, "winter 2011", 12, 22, 2011);
- validateDate(reference, "winter 1900", 12, 22, 1900);
- }
-
- @Test
- public void testHolidaysByYear() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "april fool's day 2000", 4, 1, 2000);
- validateDate(reference, "black friday 2001", 11, 23, 2001);
- validateDate(reference, "christmas 2002", 12, 25, 2002);
- validateDate(reference, "christmas eve 2003", 12, 24, 2003);
- validateDate(reference, "columbus day 2010", 10, 11, 2010);
- validateDate(reference, "earth day 2005", 4, 22, 2005);
- validateDate(reference, "easter '06", 4, 16, 2006);
- validateDate(reference, "father's day '07", 6, 17, 2007);
- validateDate(reference, "flag day '08", 6, 14, 2008);
- validateDate(reference, "good friday '09", 4, 10, 2009);
- validateDate(reference, "groundhog day '10", 2, 2, 2010);
- validateDate(reference, "halloween '11", 10, 31, 2011);
- validateDate(reference, "independence day '12", 7, 4, 2012);
- validateDate(reference, "kwanzaa '13", 12, 26, 2013);
- validateDate(reference, "labor day '14", 9, 1, 2014);
- validateDate(reference, "mlk day '15", 1, 19, 2015);
- validateDate(reference, "memorial day '16", 5, 30, 2016);
- validateDate(reference, "mother's day 2017", 5, 14, 2017);
- validateDate(reference, "new year's day 2018", 1, 1, 2018);
- validateDate(reference, "new year's eve 2019", 12, 31, 2018);
- validateDate(reference, "patriot day 2020", 9, 11, 2020);
- validateDate(reference, "president's day 2019", 2, 18, 2019);
- validateDate(reference, "st patty's day 2018", 3, 17, 2018);
- validateDate(reference, "tax day 2017", 4, 15, 2017);
- validateDate(reference, "thanksgiving 2016", 11, 24, 2016);
- validateDate(reference, "election day 2015", 11, 3, 2015);
- validateDate(reference, "valentine day 2014", 2, 14, 2014);
- validateDate(reference, "veterans day 2013", 11, 11, 2013);
- }
-
- @Test
- public void testHolidaysWithModifiers() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "four days before veterans day 2013", 11, 7, 2013);
- validateDate(reference, "two days after two thanksgivings from now", 11, 24, 2012);
- }
-
- @Test
- public void testSeasonsWithModifiers() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
- calendarSource = new CalendarSource(reference);
-
- validateDate(reference, "four days before fall 2013", 9, 18, 2013);
- validateDate(reference, "two days after two summers from now", 6, 23, 2013);
- validateDate(reference, "three summers ago", 6, 21, 2009);
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/RecurrenceTest.java b/src/test/java/com/joestelmach/natty/RecurrenceTest.java
deleted file mode 100644
index f306c502..00000000
--- a/src/test/java/com/joestelmach/natty/RecurrenceTest.java
+++ /dev/null
@@ -1,44 +0,0 @@
-package com.joestelmach.natty;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-import junit.framework.Assert;
-import org.junit.BeforeClass;
-
-import org.junit.Test;
-
-/**
- *
- * @author Joe Stelmach
- */
-public class RecurrenceTest extends AbstractTest {
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- @Test
- public void testRelative() throws Exception {
- Date reference = DateFormat.getDateTimeInstance(DateFormat.SHORT,
- DateFormat.SHORT).parse("3/3/2011 12:00 am");
- calendarSource = new CalendarSource(reference);
-
- DateGroup group = _parser.parse("every friday until two tuesdays from now", reference).get(0);
- Assert.assertEquals(1, group.getDates().size());
- validateDate(group.getDates().get(0), 3, 4, 2011);
- Assert.assertTrue(group.isRecurring());
- validateDate(group.getRecursUntil(), 3, 15, 2011);
-
- group = _parser.parse("every saturday or sunday", reference).get(0);
- Assert.assertEquals(2, group.getDates().size());
- validateDate(group.getDates().get(0), 3, 5, 2011);
- validateDate(group.getDates().get(1), 3, 6, 2011);
- Assert.assertTrue(group.isRecurring());
- Assert.assertNull(group.getRecursUntil());
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/SearchTest.java b/src/test/java/com/joestelmach/natty/SearchTest.java
deleted file mode 100644
index 2df0adac..00000000
--- a/src/test/java/com/joestelmach/natty/SearchTest.java
+++ /dev/null
@@ -1,412 +0,0 @@
-package com.joestelmach.natty;
-
-import junit.framework.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- *
- * @author Joe Stelmach
- */
-public class SearchTest extends AbstractTest {
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- @Test
- public void test() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/20/2011");
- calendarSource = new CalendarSource(reference);
-
- Parser parser = new Parser();
- List groups = parser.parse("golf tomorrow at 9 AM at pebble beach", reference);
- Assert.assertEquals(1, groups.size());
- DateGroup group = groups.get(0);
- Assert.assertEquals(1, group.getLine());
- Assert.assertEquals(6, group.getPosition());
- Assert.assertEquals(1, group.getDates().size());
- validateDate(group.getDates().get(0), 2, 21, 2011);
- validateTime(group.getDates().get(0), 9, 0, 0);
-
- groups = parser.parse("golf with friends tomorrow at 10 ", reference);
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- Assert.assertEquals(1, group.getLine());
- Assert.assertEquals(19, group.getPosition());
- Assert.assertEquals(1, group.getDates().size());
- validateDate(group.getDates().get(0), 2, 21, 2011);
- validateTime(group.getDates().get(0), 10, 0, 0);
-
- parser = new Parser();
- groups = parser.parse("golf with freinds tomorrow at 9 or Thursday at 10 am", reference);
- Assert.assertEquals(1, groups.size());
- List dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 21, 2011);
- validateTime(dates.get(0), 9, 0, 0);
- validateDate(dates.get(1), 2, 24, 2011);
- validateTime(dates.get(1), 10, 0, 0);
-
- groups = parser.parse("golf with friends tomorrow at 9 or Thursday at 10", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 21, 2011);
- validateTime(dates.get(0), 9, 0, 0);
- validateDate(dates.get(1), 2, 24, 2011);
- validateTime(dates.get(1), 10, 0, 0);
-
- groups = parser.parse("I want to go to park tomorrow and then email john@aol.com", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 21, 2011);
-
- groups = parser.parse("I want to pay off all my debt in the next two years.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 20, 2011);
- validateDate(dates.get(1), 2, 20, 2013);
-
- groups = parser.parse("I want to purchase a car in the next month.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 3, 20, 2011);
-
- groups = parser.parse("I want to plan a get-together with my friends for this Friday.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 25, 2011);
-
- groups = parser.parse("I want to lose five pounds in the next two months.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 20, 2011);
- validateDate(dates.get(1), 4, 20, 2011);
-
- groups = parser.parse("I want to finalize my college schedule by next week.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 27, 2011);
-
- groups = parser.parse("I want to read this weekend.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 26, 2011);
-
- groups = parser.parse("I want to travel a big chunk of world next year.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 20, 2012);
-
- groups = parser.parse("last 2 weeks", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 20, 2011);
- validateDate(dates.get(1), 2, 6, 2011);
-
- groups = parser.parse("last 5 years", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 20, 2011);
- validateDate(dates.get(1), 2, 20, 2006);
-
- groups = parser.parse("next 5 years", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(2, dates.size());
- validateDate(dates.get(0), 2, 20, 2011);
- validateDate(dates.get(1), 2, 20, 2016);
-
- groups = parser.parse("I want to go to my doctors appointment on May 15, 2011.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 5, 15, 2011);
-
- groups = parser.parse("I intend to become a zombie on December, 21st 2012.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 12, 21, 2012);
-
- groups = parser.parse("I want to hire a virtual assistant to do research for me on March 15, 2011", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 3, 15, 2011);
-
- groups = parser.parse("I want to see my mother on sunday.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 27, 2011);
-
- groups = parser.parse("I want to be able to jog 3 miles non-stop by September.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 1, 2011);
-
- groups = parser.parse("I want to lose 10 lbs in 10 days", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 3, 2, 2011);
-
- groups = parser.parse("I want to visit my grandfathers grave on December 30 2011", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 12, 30, 2011);
-
- groups = parser.parse("i want to have 1 kid this year", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 20, 2011);
-
- groups = parser.parse("save $1000 by September", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 1, 2011);
-
- groups = parser.parse("have my son play at muse music in provo UT at the 3 band cause they always have fog on the third band at 7:30", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDateTime(dates.get(0), 2, 20, 2011, 7, 30, 0);
-
- groups = parser.parse("i want to eat chinese tonight", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDateTime(dates.get(0), 2, 20, 2011, 20, 0, 0);
-
- groups = parser.parse("Watch School Spirits on June 20 on syfy channel", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 6, 20, 2011);
-
- groups = parser.parse("Watch School Spirits on June 20 on", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 6, 20, 2011);
-
- groups = parser.parse("Watch School Spirits on June 20", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 6, 20, 2011);
-
- groups = parser.parse("hillary clinton sep 13, 2013", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 13, 2013);
- Assert.assertEquals(17, groups.get(0).getPosition());
- Assert.assertEquals("sep 13, 2013", groups.get(0).getText());
-
- groups = parser.parse("hillary clinton 9/13/2013", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 13, 2013);
- Assert.assertEquals(17, groups.get(0).getPosition());
- Assert.assertEquals("9/13/2013", groups.get(0).getText());
-
- groups = parser.parse("hillary clintoo sep 13, 2013", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 13, 2013);
- Assert.assertEquals(17, groups.get(0).getPosition());
- Assert.assertEquals("sep 13, 2013", groups.get(0).getText());
-
- groups = parser.parse("clinton sep 13 2013", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 13, 2013);
- Assert.assertEquals(9, groups.get(0).getPosition());
- Assert.assertEquals("sep 13 2013", groups.get(0).getText());
-
- groups = parser.parse("wedding dinner with Pam", reference);
- Assert.assertEquals(0, groups.size());
-
- groups = parser.parse("yummy fried chicken", reference);
- Assert.assertEquals(0, groups.size());
-
- groups = parser.parse("I am friend with Pam", reference);
- Assert.assertEquals(0, groups.size());
-
- groups = parser.parse("bfriday blah blah", reference);
- Assert.assertEquals(0, groups.size());
-
- groups = parser.parse("dinner bmong friends", reference);
- Assert.assertEquals(0, groups.size());
-
- groups = parser.parse("I know we should meet tomorrow", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 2, 21, 2011);
-
- groups = parser.parse("**SHOT 01/31/15**", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 1, 31, 2015);
-
- groups = parser.parse("KOSTROMA REGION, RUSSIA. SEPTEMBER 24, 2014. A woman cleaning up fallen leaves on the grounds of the Shchelykovo museum reserve of Russian playwright Alexander Ostrovsky.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 24, 2014);
-
- groups = parser.parse("21 November 2014-NYC-USA **** STRICTLY NOT AVAILABLE FOR USA ***", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 11, 21, 2014);
-
- groups = parser.parse("...all the backstory I needed in the first two minutes. From there, I....", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDateTime(dates.get(0), 2, 20, 2011, 0, 2, 0);
-
- groups = parser.parse("earthquake occured 5km NNW of Vincent, California at 07:34 UTC! #earthquake #Vincent http://t.co/6e4fAC6hTU", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDateTime(dates.get(0), 2, 20, 2011, 2, 34, 0);
-
- groups = parser.parse("Caricature: Person with anti-German foreign press. From: Le Rire, Paris, Spring 1933.", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 3, 20, 1933);
-
- groups = parser.parse("Person with Generaloberst von Seeckt in Bad Nauheim. Photograph. Autumn 1936", reference);
- Assert.assertEquals(1, groups.size());
- dates = groups.get(0).getDates();
- Assert.assertEquals(1, dates.size());
- validateDate(dates.get(0), 9, 23, 1936);
- }
-
- @Test
- public void testLocations() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/20/2011");
- calendarSource = new CalendarSource(reference);
-
- Parser parser = new Parser();
- List groups = parser.parse("I want to go to the movies on september 1st. Or maybe we should go on October 3rd.", reference);
- Assert.assertEquals(2, groups.size());
- DateGroup group = groups.get(0);
- Assert.assertEquals(1, group.getLine());
- Assert.assertEquals(31, group.getPosition());
- group = groups.get(1);
- Assert.assertEquals(1, group.getLine());
- Assert.assertEquals(72, group.getPosition());
-
- groups = parser.parse("I want to go to \nthe movies on september 1st to see The Alan Turing Movie.", reference);
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- Assert.assertEquals(2, group.getLine());
- Assert.assertEquals(15, group.getPosition());
- }
-
- @Test
- public void testPrefixSuffix() throws Exception {
-
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/20/2011");
- calendarSource = new CalendarSource(reference);
-
- // no prefix or suffix
- Parser parser = new Parser();
- List groups = parser.parse("Sept. 1st");
- Assert.assertEquals(1, groups.size());
- DateGroup group = groups.get(0);
- Assert.assertEquals(0, group.getPrefix(3).length());
- Assert.assertEquals(0, group.getSuffix(3).length());
-
- // no prefix
- groups = parser.parse("Sept. 1st is the date");
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- Assert.assertEquals(0, group.getPrefix(3).length());
- String suffix = group.getSuffix(3);
- Assert.assertEquals(3, suffix.length());
- Assert.assertEquals(" is",suffix);
-
- // no suffix
- groups = parser.parse("The date is Sept. 1st");
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- String prefix = group.getPrefix(3);
- Assert.assertEquals(3, prefix.length());
- Assert.assertEquals("is ", prefix);
- Assert.assertEquals(0, group.getSuffix(3).length());
-
- // ask for a larger prefix than available
- groups = parser.parse("a Sept. 1st");
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- prefix = group.getPrefix(5);
- Assert.assertEquals(2, prefix.length());
- Assert.assertEquals("a ", prefix);
- Assert.assertEquals(0, group.getSuffix(3).length());
-
- // ask for a larger suffix than available
- groups = parser.parse("Sept. 1st a");
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- suffix = group.getSuffix(5);
- Assert.assertEquals(2,suffix.length());
- Assert.assertEquals(" a", suffix);
- Assert.assertEquals(0, group.getPrefix(3).length());
-
- // ask for a larger prefix and suffix than available
- groups = parser.parse("a Sept. 1st a");
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- prefix = group.getPrefix(5);
- suffix = group.getSuffix(5);
- Assert.assertEquals(2,prefix.length());
- Assert.assertEquals("a ", prefix);
- Assert.assertEquals(2,suffix.length());
- Assert.assertEquals(" a", suffix);
- }
-
- @Test
- public void testNoDates() {
- List dates = parseCollection(new Date(), "Fried Chicken, Wedding Dinner");
- Assert.assertEquals(0, dates.size());
-
- parseCollection(new Date(), "Cleveland");
- Assert.assertEquals(0, dates.size());
- }
-
-}
diff --git a/src/test/java/com/joestelmach/natty/ThreadSafetyTest.java b/src/test/java/com/joestelmach/natty/ThreadSafetyTest.java
deleted file mode 100644
index 8d2774dc..00000000
--- a/src/test/java/com/joestelmach/natty/ThreadSafetyTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-package com.joestelmach.natty;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.concurrent.atomic.AtomicInteger;
-import java.util.TimeZone;
-
-import org.junit.Assert;
-
-import org.junit.Test;
-import org.junit.BeforeClass;
-
-public class ThreadSafetyTest extends AbstractTest {
-
- private final static int NUM_OF_THREADS = 10;
- private final static int JOIN_TIMEOUT = 2000; // 2 seconds
- private static DateFormat dateFormat;
-
- private AtomicInteger numOfCorrectResults = new AtomicInteger();
-
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.US);
- initCalendarAndParser();
- }
-
- @Test
- public void testManyThreads() throws Exception {
- Thread[] threads = new Thread[NUM_OF_THREADS];
- for (int i = 0; i < NUM_OF_THREADS; i++) {
- threads[i] = new Thread(new Tester(i));
- }
- for (Thread thread : threads) {
- thread.start();
- }
- for (Thread thread : threads) {
- thread.join(JOIN_TIMEOUT);
- }
- Assert.assertEquals(NUM_OF_THREADS, numOfCorrectResults.get());
- }
-
- private class Tester implements Runnable {
-
- private Date referenceDate;
- private int baseMinute;
-
- public Tester(int baseMinute) throws Exception {
- String date = String.format("3/3/2011 1:%02d am", baseMinute);
- this.referenceDate = dateFormat.parse(date);
- this.baseMinute = baseMinute;
- }
-
- public void run() {
- try {
- // Immitate some long running task.
- Thread.sleep(100);
- } catch (Exception e) { }
- String newDate = "4/4/2012";
- Date parsed = _parser.parse(newDate, referenceDate).get(0).getDates().get(0);
- validateThread(parsed, baseMinute);
- numOfCorrectResults.incrementAndGet();
- }
- }
-
- // We need this method, because validateDate and validateTime are not thread safe.
- private synchronized void validateThread(Date date, int baseMinute) {
- validateDate(date, 4, 4, 2012);
- validateTime(date, 1, baseMinute, 0);
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/TimeTest.java b/src/test/java/com/joestelmach/natty/TimeTest.java
deleted file mode 100644
index 3d4bb70e..00000000
--- a/src/test/java/com/joestelmach/natty/TimeTest.java
+++ /dev/null
@@ -1,158 +0,0 @@
-package com.joestelmach.natty;
-
-import org.junit.Assert;
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.List;
-import java.util.Locale;
-import java.util.TimeZone;
-
-/**
- * Runs the parser through the various time formats
- *
- * @author Joe Stelmach
- */
-public class TimeTest extends AbstractTest {
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- /**
- * Runs the parser through the various time formats
- * @throws Exception
- */
- @Test
- public void testFormal() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("1/02/2011");
- calendarSource = new CalendarSource(reference);
- validateTime(reference, "0600h", 6, 0, 0);
- validateTime(reference, "06:00h", 6, 0, 0);
- validateTime(reference, "06:00 hours", 6, 0, 0);
- validateTime(reference, "0000", 0, 0, 0);
- validateTime(reference, "0700h", 7, 0, 0);
- validateTime(reference, "6pm", 18, 0, 0);
- validateTime(reference, "5:30 a.m.", 5, 30, 0);
- validateTime(reference, "5", 5, 0, 0);
- validateTime(reference, "12:59", 12, 59, 0);
- validateTime(reference, "23:59:28", 23, 59, 28);
- validateTime(reference, "00:00", 0, 0, 0);
- validateTime(reference, "10:00am", 10, 0, 0);
- validateTime(reference, "10a", 10, 0, 0);
- validateTime(reference, "10am", 10, 0, 0);
- validateTime(reference, "10a_m", 10, 0, 0);
- validateTime(reference, "10", 10, 0, 0);
- validateTime(reference, "8p", 20, 0, 0);
- validateTime(reference, "8pm", 20, 0, 0);
- validateTime(reference, "8 pm", 20, 0, 0);
- validateTime(reference, "8 p_m", 20, 0, 0);
- }
-
- @Test
- public void testRelaxed() throws Exception {
- Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("1/02/2011");
- calendarSource = new CalendarSource(reference);
- validateTime(reference, "noon", 12, 0, 0);
- validateTime(reference, "at noon", 12, 0, 0);
- validateTime(reference, "afternoon", 12, 0, 0);
- validateTime(reference, "midnight", 0, 0, 0);
- validateTime(reference, "mid-night", 0, 0, 0);
- validateTime(reference, "6 in the morning", 6, 0, 0);
- validateTime(reference, "4 in the afternoon", 16, 0, 0);
- validateTime(reference, "evening", 19, 0, 0);
- validateTime(reference, "10 hours before noon", 2, 0, 0);
- validateTime(reference, "10 hours before midnight", 14, 0, 0);
- validateTime(reference, "5 hours after noon", 17, 0, 0);
- validateTime(reference, "5 hours after midnight", 5, 0, 0);
- validateTime(reference, "tonight", 20, 0, 0);
- }
-
- @Test
- public void testRelative() throws Exception {
- Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
- calendarSource = new CalendarSource(reference);
- validateTime(reference, "in 5 seconds", 12, 0, 5);
- validateTime(reference, "in 5 minutes", 12, 5, 0);
- validateTime(reference, "in 5 hours", 17, 0, 0);
- validateTime(reference, "4 seconds from now", 12, 0, 4);
- validateTime(reference, "4 minutes from now", 12, 4, 0);
- validateTime(reference, "4 hours from now", 16, 0, 0);
- validateTime(reference, "next minute", 12, 1, 0);
- validateTime(reference, "last minute", 11, 59, 0);
- validateTime(reference, "next second", 12, 0, 1);
- validateTime(reference, "this second", 12, 0, 0);
- validateTime(reference, "this minute", 12, 0, 0);
- validateTime(reference, "this hour", 12, 0, 0);
- }
-
- @Test
- public void testAlternatives() throws Exception {
- Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
- calendarSource = new CalendarSource(reference);
-
- List dates = parseCollection(reference, "12 or 12:30");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 12, 0, 0);
- validateTime(dates.get(1), 12, 30, 0);
-
- dates = parseCollection(reference, "12pm or 12:30");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 12, 0, 0);
- validateTime(dates.get(1), 12, 30, 0);
-
- dates = parseCollection(reference, "noon or 12:30");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 12, 0, 0);
- validateTime(dates.get(1), 12, 30, 0);
-
- dates = parseCollection(reference, "12 or 12:30am");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 0, 0, 0);
- validateTime(dates.get(1), 0, 30, 0);
- }
-
- @Test
- public void testRange() throws Exception {
- Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
- calendarSource = new CalendarSource(reference);
-
- List dates = parseCollection(reference, "for six hours");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 12, 0, 0);
- validateTime(dates.get(1), 18, 0, 0);
-
- dates = parseCollection(reference, "for 12 minutes");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 12, 0, 0);
- validateTime(dates.get(1), 12, 12, 0);
-
- dates = parseCollection(reference, "for 10 seconds");
- Assert.assertEquals(2, dates.size());
- validateTime(dates.get(0), 12, 0, 0);
- validateTime(dates.get(1), 12, 0, 10);
- }
-
- @Test
- public void testText() throws Exception {
- Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
-
- List groups = _parser.parse("5.30pm", reference);
- Assert.assertEquals(1, groups.size());
- DateGroup group = groups.get(0);
- Assert.assertEquals(1, group.getDates().size());
- validateTime(group.getDates().get(0), 17, 30, 0);
- Assert.assertEquals("5.30pm", group.getText());
-
- groups = _parser.parse("5:30pm", reference);
- Assert.assertEquals(1, groups.size());
- group = groups.get(0);
- Assert.assertEquals(1, group.getDates().size());
- validateTime(group.getDates().get(0), 17, 30, 0);
- Assert.assertEquals("5:30pm", group.getText());
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/TimeZoneTest.java b/src/test/java/com/joestelmach/natty/TimeZoneTest.java
deleted file mode 100644
index 5dfb8308..00000000
--- a/src/test/java/com/joestelmach/natty/TimeZoneTest.java
+++ /dev/null
@@ -1,41 +0,0 @@
-package com.joestelmach.natty;
-
-import org.junit.BeforeClass;
-import org.junit.Test;
-
-import java.text.DateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.TimeZone;
-
-public class TimeZoneTest extends AbstractTest {
-
- @BeforeClass
- public static void oneTime() {
- Locale.setDefault(Locale.US);
- TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
- initCalendarAndParser();
- }
-
- @Test
- public void testSpecific() throws Exception {
- Date reference = DateFormat.getDateTimeInstance(DateFormat.SHORT,
- DateFormat.SHORT).parse("5/19/2012 12:00 am");
- calendarSource = new CalendarSource(reference);
-
- validateDateTime(reference, "2011-06-17T07:00:00Z", 6, 17, 2011, 3, 0, 0);
- validateDateTime(reference, "05-Aug-2013 14:10:56 UTC", 8, 5, 2013, 10, 10, 56);
- validateDateTime(reference, "5/1/13 01:00:00-8", 5, 1, 2013, 5, 0, 0);
- validateDateTime(reference, "5/1/13 01:00:00 UTC", 4, 30, 2013, 21, 0, 0);
- validateDateTime(reference, "5/1/13 01:00:00 UTC+8", 4, 30, 2013, 13, 0, 0);
- validateDateTime(reference, "5/1/13 01:00:00 GMT-1", 4, 30, 2013, 22, 0, 0);
- validateDateTime(reference, "tomorrow, 10 eastern time", 5, 20, 2012, 10, 0, 0);
- validateDateTime(reference, "tomorrow, 10 central time", 5, 20, 2012, 11, 0, 0);
- validateDateTime(reference, "tomorrow, 10 central", 5, 20, 2012, 11, 0, 0);
- validateDateTime(reference, "tomorrow, 10 mountain time", 5, 20, 2012, 12, 0, 0);
- validateDateTime(reference, "tomorrow, 10 pacific time", 5, 20, 2012, 13, 0, 0);
- validateDateTime(reference, "tomorrow, 10pm pacific", 5, 21, 2012, 1, 0, 0);
- validateDateTime(reference, "tomorrow, 10 alaska time", 5, 20, 2012, 14, 0, 0);
- validateDateTime(reference, "tomorrow, 10 hawaii time", 5, 20, 2012, 16, 0, 0);
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/grammar/AbstractGrammarTest.java b/src/test/java/com/joestelmach/natty/grammar/AbstractGrammarTest.java
deleted file mode 100644
index 1e3a69fc..00000000
--- a/src/test/java/com/joestelmach/natty/grammar/AbstractGrammarTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-package com.joestelmach.natty.grammar;
-
-import java.io.ByteArrayInputStream;
-import java.lang.reflect.Method;
-
-import junit.framework.Assert;
-
-import org.antlr.runtime.ANTLRInputStream;
-import org.antlr.runtime.CommonTokenStream;
-import org.antlr.runtime.ParserRuleReturnScope;
-import org.antlr.runtime.tree.CommonTree;
-import org.antlr.runtime.tree.CommonTreeNodeStream;
-import org.antlr.runtime.tree.Tree;
-
-import com.joestelmach.natty.ANTLRNoCaseInputStream;
-import com.joestelmach.natty.ParseListener;
-import com.joestelmach.natty.generated.DateLexer;
-import com.joestelmach.natty.generated.DateParser;
-import com.joestelmach.natty.generated.TreeRewrite;
-
-public abstract class AbstractGrammarTest {
- protected String _ruleName;
-
- /**
- *
- * @param input
- * @param ast
- */
- protected void assertAST(String input, String ast) throws Exception {
- Assert.assertEquals(ast, buildAST(input));
- }
-
- /**
- *
- * @param value
- * @return
- * @throws Exception
- */
- protected String buildAST(String value) throws Exception {
- DateParser parser = buildParser(value);
- Class> klass = Class.forName("com.joestelmach.natty.generated.DateParser");
- Method meth = klass.getMethod(_ruleName, (Class>[]) null);
- ParserRuleReturnScope ret = (ParserRuleReturnScope) meth.invoke(parser, (Object[]) null);
-
- Tree tree = (Tree)ret.getTree();
- // rewrite the tree (temporary fix for http://www.antlr.org/jira/browse/ANTLR-427)
- CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
- TreeRewrite s = new TreeRewrite(nodes);
- tree = (CommonTree)s.downup(tree);
-
- return tree.toStringTree();
- }
-
- /**
- *
- * @param value
- * @return
- */
- private DateParser buildParser(String value) throws Exception {
- // lex
- ANTLRInputStream input = new ANTLRNoCaseInputStream(
- new ByteArrayInputStream(value.getBytes()));
- DateLexer lexer = new DateLexer(input);
- CommonTokenStream tokens = new CommonTokenStream(lexer);
-
- // parse
- ParseListener listener = new ParseListener();
- return new DateParser(tokens, listener);
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/grammar/DateGrammarTest.java b/src/test/java/com/joestelmach/natty/grammar/DateGrammarTest.java
deleted file mode 100644
index ebae82f9..00000000
--- a/src/test/java/com/joestelmach/natty/grammar/DateGrammarTest.java
+++ /dev/null
@@ -1,638 +0,0 @@
-package com.joestelmach.natty.grammar;
-
-import org.junit.Test;
-
-public class DateGrammarTest extends AbstractGrammarTest {
- @Test
- public void date() throws Exception {
- _ruleName = "date";
-
- assertAST("the day before yesterday", "(RELATIVE_DATE (SEEK < by_day 1 (RELATIVE_DATE (SEEK < by_day 1 day))))");
- assertAST("1st oct in the year '89", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89))");
- assertAST("2009-10-10", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10) (YEAR_OF 2009))");
- assertAST("seven years ago", "(RELATIVE_DATE (SEEK < by_day 7 year))");
- assertAST("next monday", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 2)))");
- }
-
- @Test
- public void alternative_day_of_month_list() throws Exception {
- _ruleName = "alternative_day_of_month_list";
-
- assertAST("mon may 15 or 16",
- "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
-
- assertAST("mon may 15 to 16",
- "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
-
- assertAST("mon may 15 and 16",
- "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
-
- assertAST("mon may 15 through 16",
- "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
-
- assertAST("mon may 15 or 16",
- "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
-
- assertAST("first or last day of september",
- "(DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))) (DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))))");
-
- assertAST("first or last day of september at 5pm",
- "(DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm))");
-
-
- assertAST("first or last day of next september at 6am",
- "(DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am))");
-
- assertAST("first or last day of 2 septembers from now at 5pm",
- "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm))");
- }
-
- @Test
- public void global_date_prefix() throws Exception {
- _ruleName = "global_date_prefix";
-
- assertAST("the day after", "> by_day 1");
- assertAST("day after", "> by_day 1");
- assertAST("2 days after", "> by_day 2");
- assertAST("three days before", "< by_day 3");
- assertAST("six months after", "> by_month 6");
- assertAST("3 weeks before", "< by_week 3");
- assertAST("10 years after", "> by_year 10");
- assertAST("the day before", "< by_day 1");
- assertAST("day before", "< by_day 1");
- }
-
- @Test
- public void relaxed_date() throws Exception {
- _ruleName = "relaxed_date";
-
- assertAST("oct 1, 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
- assertAST("oct. 1, 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
- assertAST("oct 1,1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
- assertAST("1st oct in the year '89", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89))");
- assertAST("thirty first of december '80", "(EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 31) (YEAR_OF 80))");
- assertAST("the first of december in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
- assertAST("the 2 of february in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
- assertAST("the 2nd of february in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
- assertAST("the second of february in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
- assertAST("jan. 2nd", "(EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 2))");
- assertAST("sun, nov 21 2010", "(EXPLICIT_DATE (MONTH_OF_YEAR 11) (DAY_OF_MONTH 21) (DAY_OF_WEEK 1) (YEAR_OF 2010))");
- }
-
- @Test
- public void formal_date() throws Exception {
- _ruleName = "formal_date";
-
- assertAST("2009-10-10", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10) (YEAR_OF 2009))");
- assertAST("1980-1-2", "(EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
- assertAST("12/12/12", "(EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 12) (YEAR_OF 12))");
- assertAST("3/4", "(EXPLICIT_DATE (MONTH_OF_YEAR 3) (DAY_OF_MONTH 4))");
- assertAST("sun, 11/21/2010", "(EXPLICIT_DATE (MONTH_OF_YEAR 11) (DAY_OF_MONTH 21) (DAY_OF_WEEK 1) (YEAR_OF 2010))");
- }
-
- @Test
- public void formal_month_of_year() throws Exception {
- _ruleName = "formal_month_of_year";
-
- assertAST("01", "(MONTH_OF_YEAR 01)");
- assertAST("1", "(MONTH_OF_YEAR 1)");
- assertAST("02", "(MONTH_OF_YEAR 02)");
- assertAST("2", "(MONTH_OF_YEAR 2)");
- assertAST("03", "(MONTH_OF_YEAR 03)");
- assertAST("3", "(MONTH_OF_YEAR 3)");
- assertAST("04", "(MONTH_OF_YEAR 04)");
- assertAST("4", "(MONTH_OF_YEAR 4)");
- assertAST("05", "(MONTH_OF_YEAR 05)");
- assertAST("5", "(MONTH_OF_YEAR 5)");
- assertAST("06", "(MONTH_OF_YEAR 06)");
- assertAST("6", "(MONTH_OF_YEAR 6)");
- assertAST("07", "(MONTH_OF_YEAR 07)");
- assertAST("7", "(MONTH_OF_YEAR 7)");
- assertAST("08", "(MONTH_OF_YEAR 08)");
- assertAST("8", "(MONTH_OF_YEAR 8)");
- assertAST("09", "(MONTH_OF_YEAR 09)");
- assertAST("9", "(MONTH_OF_YEAR 9)");
- assertAST("10", "(MONTH_OF_YEAR 10)");
- assertAST("11", "(MONTH_OF_YEAR 11)");
- assertAST("12", "(MONTH_OF_YEAR 12)");
- //"00" FAIL
- //"0" FAIL
- //"13" FAIL
- }
-
- @Test
- public void formal_day_of_month() throws Exception {
- _ruleName = "formal_day_of_month";
-
- assertAST("01", "(DAY_OF_MONTH 01)");
- assertAST("1", "(DAY_OF_MONTH 1)");
- assertAST("02", "(DAY_OF_MONTH 02)");
- assertAST("2", "(DAY_OF_MONTH 2)");
- assertAST("03", "(DAY_OF_MONTH 03)");
- assertAST("3", "(DAY_OF_MONTH 3)");
- assertAST("04", "(DAY_OF_MONTH 04)");
- assertAST("4", "(DAY_OF_MONTH 4)");
- assertAST("05", "(DAY_OF_MONTH 05)");
- assertAST("5", "(DAY_OF_MONTH 5)");
- assertAST("06", "(DAY_OF_MONTH 06)");
- assertAST("6", "(DAY_OF_MONTH 6)");
- assertAST("07", "(DAY_OF_MONTH 07)");
- assertAST("7", "(DAY_OF_MONTH 7)");
- assertAST("08", "(DAY_OF_MONTH 08)");
- assertAST("8", "(DAY_OF_MONTH 8)");
- assertAST("09", "(DAY_OF_MONTH 09)");
- assertAST("9", "(DAY_OF_MONTH 9)");
- assertAST("10", "(DAY_OF_MONTH 10)");
- assertAST("11", "(DAY_OF_MONTH 11)");
- assertAST("12", "(DAY_OF_MONTH 12)");
- assertAST("13", "(DAY_OF_MONTH 13)");
- assertAST("14", "(DAY_OF_MONTH 14)");
- assertAST("15", "(DAY_OF_MONTH 15)");
- assertAST("16", "(DAY_OF_MONTH 16)");
- assertAST("17", "(DAY_OF_MONTH 17)");
- assertAST("18", "(DAY_OF_MONTH 18)");
- assertAST("19", "(DAY_OF_MONTH 19)");
- assertAST("20", "(DAY_OF_MONTH 20)");
- assertAST("21", "(DAY_OF_MONTH 21)");
- assertAST("22", "(DAY_OF_MONTH 22)");
- assertAST("23", "(DAY_OF_MONTH 23)");
- assertAST("24", "(DAY_OF_MONTH 24)");
- assertAST("25", "(DAY_OF_MONTH 25)");
- assertAST("26", "(DAY_OF_MONTH 26)");
- assertAST("27", "(DAY_OF_MONTH 27)");
- assertAST("28", "(DAY_OF_MONTH 28)");
- assertAST("29", "(DAY_OF_MONTH 29)");
- assertAST("30", "(DAY_OF_MONTH 30)");
- assertAST("31", "(DAY_OF_MONTH 31)");
- //"00" FAIL
- //"0" FAIL
- //"32" FAIL
- }
-
- @Test
- public void formal_year() throws Exception {
- _ruleName = "formal_year";
-
- assertAST("1999", "(YEAR_OF 1999)");
- assertAST("80", "(YEAR_OF 80)");
- assertAST("0000", "(YEAR_OF 0000)");
- assertAST("2010", "(YEAR_OF 2010)");
- assertAST("03", "(YEAR_OF 03)");
- //"037" FAIL
- //"0" FAIL
- //"03700" FAIL
- }
-
- @Test
- public void formal_year_four_digits() throws Exception {
- _ruleName = "formal_year_four_digits";
-
- assertAST("1999", "(YEAR_OF 1999)");
- assertAST("0000", "(YEAR_OF 0000)");
- assertAST("2010", "(YEAR_OF 2010)");
- //assertAST("80" FAIL
- //assertAST("03" FAIL
- //assertAST("037" FAIL
- //assertAST("0" FAIL
- //assertAST("03700" FAIL
- }
-
- @Test
- public void formal_date_separator() throws Exception {
- _ruleName = "formal_date_separator";
-
- assertAST("-", "-");
- assertAST("/", "/");
- }
-
- @Test
- public void relative_date() throws Exception {
- _ruleName = "relative_date";
-
- assertAST("yesterday", "(RELATIVE_DATE (SEEK < by_day 1 day))");
- assertAST("tomorrow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
- assertAST("in 3 days", "(RELATIVE_DATE (SEEK > by_day 3 day))");
- assertAST("3 days ago", "(RELATIVE_DATE (SEEK < by_day 3 day))");
- assertAST("in 3 weeks", "(RELATIVE_DATE (SEEK > by_day 3 week))");
- assertAST("four weeks ago", "(RELATIVE_DATE (SEEK < by_day 4 week))");
- assertAST("in 3 months", "(RELATIVE_DATE (SEEK > by_day 3 month))");
- assertAST("three months ago", "(RELATIVE_DATE (SEEK < by_day 3 month))");
- assertAST("in 3 years", "(RELATIVE_DATE (SEEK > by_day 3 year))");
- assertAST("seven years ago", "(RELATIVE_DATE (SEEK < by_day 7 year))");
- assertAST("60 years ago", "(RELATIVE_DATE (SEEK < by_day 60 year))");
- assertAST("32 days ago", "(RELATIVE_DATE (SEEK < by_day 32 day))");
- assertAST("150 days ago", "(RELATIVE_DATE (SEEK < by_day 150 day))");
- assertAST("1500 days ago", "(RELATIVE_DATE (SEEK < by_day 1500 day))");
- assertAST("next monday", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 2)))");
- assertAST("next mon", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 2)))");
- assertAST("4 mondays from now", "(RELATIVE_DATE (SEEK > by_day 4 (DAY_OF_WEEK 2)))");
- assertAST("4 mondays from today", "(RELATIVE_DATE (SEEK > by_day 4 (DAY_OF_WEEK 2)))");
- assertAST("next weekend", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 7)))");
- assertAST("six mondays ago", "(RELATIVE_DATE (SEEK < by_day 6 (DAY_OF_WEEK 2)))");
- assertAST("last monday", "(RELATIVE_DATE (SEEK < by_week 1 (DAY_OF_WEEK 2)))");
- assertAST("last mon", "(RELATIVE_DATE (SEEK < by_week 1 (DAY_OF_WEEK 2)))");
- assertAST("this past mon", "(RELATIVE_DATE (SEEK < by_day 1 (DAY_OF_WEEK 2)))");
- assertAST("this coming mon", "(RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 2)))");
- assertAST("this upcoming mon", "(RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 2)))");
- assertAST("next thurs", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5)))");
- assertAST("next month", "(RELATIVE_DATE (SEEK > by_week 1 month))");
- assertAST("last month", "(RELATIVE_DATE (SEEK < by_week 1 month))");
- assertAST("next week", "(RELATIVE_DATE (SEEK > by_week 1 week))");
- assertAST("last week", "(RELATIVE_DATE (SEEK < by_week 1 week))");
- assertAST("next year", "(RELATIVE_DATE (SEEK > by_week 1 year))");
- assertAST("last year", "(RELATIVE_DATE (SEEK < by_week 1 year))");
- assertAST("1 year 2 months ago", "(RELATIVE_DATE (SEEK < by_day 1 year) (SEEK < by_day 2 month))");
- assertAST("1 year 2 months 3 days ago", "(RELATIVE_DATE (SEEK < by_day 1 year) (SEEK < by_day 2 month) (SEEK < by_day 3 day))");
- assertAST("5 years 9 days after now","(RELATIVE_DATE (SEEK > by_day 5 year) (SEEK > by_day 9 day))");
- assertAST("5 years 3 months 9 days from now","(RELATIVE_DATE (SEEK > by_day 5 year) (SEEK > by_day 3 month) (SEEK > by_day 9 day))");
- }
-
- @Test
- public void explicit_relative_date() throws Exception {
- _ruleName = "explicit_relative_date";
-
- assertAST("monday of last week",
- "(RELATIVE_DATE (SEEK < by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("tuesday of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 3)))");
-
- assertAST("the monday of 2 weeks ago",
- "(RELATIVE_DATE (SEEK < by_day 2 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("tuesday of 3 weeks from now",
- "(RELATIVE_DATE (SEEK > by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 3)))");
-
- assertAST("monday of 3 weeks from now",
- "(RELATIVE_DATE (SEEK > by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("1st of three months ago",
- "(RELATIVE_DATE (SEEK < by_day 3 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
-
- assertAST("10th of next month",
- "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 10)))");
-
- assertAST("28th of last month",
- "(RELATIVE_DATE (SEEK < by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 28)))");
-
- assertAST("10th of next october",
- "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 10)) (EXPLICIT_SEEK (DAY_OF_MONTH 10)))");
-
- assertAST("the 30th of this month",
- "(RELATIVE_DATE (SEEK > by_day 0 month) (EXPLICIT_SEEK (DAY_OF_MONTH 30)))");
-
- assertAST("10th of the month after next",
- "(RELATIVE_DATE (SEEK > by_day 2 month) (EXPLICIT_SEEK (DAY_OF_MONTH 10)))");
-
- assertAST("the last thursday in november",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5)))");
-
- assertAST("the last thursday in november 1999",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK (YEAR_OF 1999)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5)))");
-
- assertAST("3rd wed in next month",
- "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK 3 (DAY_OF_WEEK 4)))");
-
- assertAST("the last sunday in november",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 1)))");
-
- assertAST("the first wed. in january",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 1)) (EXPLICIT_SEEK 1 (DAY_OF_WEEK 4)))");
-
- assertAST("the last day of february 1999",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 2)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)) (EXPLICIT_SEEK (YEAR_OF 1999)))");
-
- assertAST("the first wed. in january in the year 2004",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 1)) (EXPLICIT_SEEK (YEAR_OF 2004)) (EXPLICIT_SEEK 1 (DAY_OF_WEEK 4)))");
-
- assertAST("last monday of last month",
- "(RELATIVE_DATE (SEEK < by_week 1 month) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 2)))");
-
- assertAST("the last sunday of next nov",
- "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 1)))");
-
- assertAST("the 3rd sunday of 2 novembers from now",
- "(RELATIVE_DATE (SEEK > by_day 2 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 3 (DAY_OF_WEEK 1)))");
-
- assertAST("the last monday in 2 novembers ago",
- "(RELATIVE_DATE (SEEK < by_day 2 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 2)))");
-
- assertAST("the beginning of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("the end of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("the end of this week",
- "(RELATIVE_DATE (SEEK > by_day 0 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("the start of this week",
- "(RELATIVE_DATE (SEEK > by_day 0 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("start of 3 weeks from now",
- "(RELATIVE_DATE (SEEK > by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("the end of 3 weeks ago",
- "(RELATIVE_DATE (SEEK < by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("the first day of this week",
- "(RELATIVE_DATE (SEEK > by_day 0 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("the last day of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("first day of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
-
- assertAST("last day of last week",
- "(RELATIVE_DATE (SEEK < by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("start of 3 months from now",
- "(RELATIVE_DATE (SEEK > by_day 3 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
-
- assertAST("beginning of next month",
- "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
-
- assertAST("end of next month",
- "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
-
- assertAST("last day of next month",
- "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
-
- assertAST("first day of 3 months from now",
- "(RELATIVE_DATE (SEEK > by_day 3 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
-
- assertAST("end of next october",
- "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 10)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
-
- assertAST("first day of feb",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 2)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
-
- assertAST("last day of three februarys from now",
- "(RELATIVE_DATE (SEEK > by_day 3 (MONTH_OF_YEAR 2)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
-
- assertAST("in the end of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("at the end of last week",
- "(RELATIVE_DATE (SEEK < by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("at the end of 2 weeks",
- "(RELATIVE_DATE (SEEK > by_day 2 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("in the start of june",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 6)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
-
- assertAST("at the end of next week",
- "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
-
- assertAST("at the end of last month",
- "(RELATIVE_DATE (SEEK < by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
-
- assertAST("the second day of april",
- "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 4)) (EXPLICIT_SEEK (DAY_OF_MONTH 2)))");
-
- assertAST("the thirtieth day of next april",
- "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 4)) (EXPLICIT_SEEK (DAY_OF_MONTH 30)))");
- }
-
- @Test
- public void relative_occurrence_index() throws Exception {
- _ruleName = "relative_occurrence_index";
-
- assertAST("1", "1");
- assertAST("2", "2");
- assertAST("3", "3");
- assertAST("4", "4");
- assertAST("5", "5");
- assertAST("first", "1");
- assertAST("second", "2");
- assertAST("third", "3");
- assertAST("fourth", "4");
- assertAST("fifth", "5");
- assertAST("last", "5");
- //assertAST("sixth" FAIL);
- //assertAST("6" FAIL);
- }
-
- @Test
- public void relative_target() throws Exception {
- _ruleName = "relative_target";
-
- assertAST("sunday" , "(DAY_OF_WEEK 1)");
- assertAST("sundays" , "(DAY_OF_WEEK 1)");
- assertAST("sun" , "(DAY_OF_WEEK 1)");
- assertAST("monday" , "(DAY_OF_WEEK 2)");
- assertAST("mondays" , "(DAY_OF_WEEK 2)");
- assertAST("mon" , "(DAY_OF_WEEK 2)");
- assertAST("tuesday" , "(DAY_OF_WEEK 3)");
- assertAST("tuesdays" , "(DAY_OF_WEEK 3)");
- assertAST("tues" , "(DAY_OF_WEEK 3)");
- assertAST("tue" , "(DAY_OF_WEEK 3)");
- assertAST("wednesday" , "(DAY_OF_WEEK 4)");
- assertAST("wednesdays", "(DAY_OF_WEEK 4)");
- assertAST("wed" , "(DAY_OF_WEEK 4)");
- assertAST("thursday" , "(DAY_OF_WEEK 5)");
- assertAST("thursdays" , "(DAY_OF_WEEK 5)");
- assertAST("thur" , "(DAY_OF_WEEK 5)");
- assertAST("thu" , "(DAY_OF_WEEK 5)");
- assertAST("friday" , "(DAY_OF_WEEK 6)");
- assertAST("fridays" , "(DAY_OF_WEEK 6)");
- assertAST("fri" , "(DAY_OF_WEEK 6)");
- assertAST("saturday" , "(DAY_OF_WEEK 7)");
- assertAST("saturdays" , "(DAY_OF_WEEK 7)");
- assertAST("sat" , "(DAY_OF_WEEK 7)");
- assertAST("day", "day");
- assertAST("days", "day");
- assertAST("week", "week");
- assertAST("weeks", "week");
- assertAST("month", "month");
- assertAST("months", "month");
- assertAST("year", "year");
- assertAST("years", "year");
- }
-
- @Test
- public void relaxed_day_of_month() throws Exception {
- _ruleName = "relaxed_day_of_month";
-
- assertAST("three", "(DAY_OF_MONTH 3)");
- assertAST("third", "(DAY_OF_MONTH 3)");
- assertAST("3rd", "(DAY_OF_MONTH 3)");
- assertAST("3", "(DAY_OF_MONTH 3)");
- assertAST("03", "(DAY_OF_MONTH 03)");
- assertAST("21", "(DAY_OF_MONTH 21)");
- assertAST("thirty one", "(DAY_OF_MONTH 31)");
- assertAST("thirty-one", "(DAY_OF_MONTH 31)");
- assertAST("thirty first", "(DAY_OF_MONTH 31)");
- assertAST("thirty-first", "(DAY_OF_MONTH 31)");
- assertAST("31st", "(DAY_OF_MONTH 31)");
- //assertAST("32" FAIL
- }
-
- @Test
- public void relaxed_year() throws Exception {
- _ruleName = "relaxed_year";
-
- assertAST("'69", "(YEAR_OF 69)");
- assertAST("79", "(YEAR_OF 79)");
- assertAST("2079", "(YEAR_OF 2079)");
- assertAST("'80", "(YEAR_OF 80)");
- assertAST("1979", "(YEAR_OF 1979)");
- assertAST("2004", "(YEAR_OF 2004)");
- //assertAST("999" FAIL");
- //assertAST("999" FAIL");
- }
-
- @Test
- public void relaxed_year_prefix() throws Exception {
- _ruleName = "relaxed_year_prefix";
-
- //assertAST(", in the year ", ", in the year");
- //assertAST(" in the year ", " in the year");
- //assertAST("in the year ", "in the year");
- //assertAST("in the yesr ", "in the year");
- }
-
- @Test
- public void implicit_prefix() throws Exception {
- _ruleName = "implicit_prefix";
-
- assertAST("this", "> by_day 0");
- }
-
- @Test
- public void relative_date_prefix() throws Exception {
- _ruleName = "relative_date_prefix";
-
- assertAST("this last" , "< by_week 1");
- assertAST("last" , "< by_week 1");
- assertAST("this past" , "< by_day 1");
- assertAST("past" , "< by_day 1");
- assertAST("this next" , "> by_week 1");
- assertAST("next" , "> by_week 1");
- assertAST("this coming" , "> by_day 1");
- assertAST("coming" , "> by_day 1");
- assertAST("this upcoming", "> by_day 1");
- assertAST("upcoming" , "> by_day 1");
- assertAST("3" , "> by_day 3");
- assertAST("twenty-eight" , "> by_day 28");
- //assertAST("in 3" , "> by_day 3");
- //assertAST("in twenty" , "> by_day 20");
- }
-
- @Test
- public void relative_date_suffix() throws Exception {
- _ruleName = "relative_date_suffix";
-
- assertAST("from now", "> by_day");
- assertAST("ago", "< by_day");
- }
-
- @Test
- public void relative_date_span() throws Exception {
- _ruleName = "relative_date_span";
-
- assertAST("day", "day");
- assertAST("days", "day");
- assertAST("week", "week");
- assertAST("weeks", "week");
- assertAST("month", "month");
- assertAST("months", "month");
- assertAST("year", "year");
- assertAST("years", "year");
- }
-
- @Test
- public void relaxed_month() throws Exception {
- _ruleName = "relaxed_month";
-
- assertAST("january", "(MONTH_OF_YEAR 1)");
- assertAST("jan", "(MONTH_OF_YEAR 1)");
- assertAST("february", "(MONTH_OF_YEAR 2)");
- assertAST("feb", "(MONTH_OF_YEAR 2)");
- assertAST("march", "(MONTH_OF_YEAR 3)");
- assertAST("mar", "(MONTH_OF_YEAR 3)");
- assertAST("april", "(MONTH_OF_YEAR 4)");
- assertAST("apr", "(MONTH_OF_YEAR 4)");
- assertAST("may", "(MONTH_OF_YEAR 5)");
- assertAST("june", "(MONTH_OF_YEAR 6)");
- assertAST("jun", "(MONTH_OF_YEAR 6)");
- assertAST("july", "(MONTH_OF_YEAR 7)");
- assertAST("jul", "(MONTH_OF_YEAR 7)");
- assertAST("august", "(MONTH_OF_YEAR 8)");
- assertAST("aug", "(MONTH_OF_YEAR 8)");
- assertAST("september", "(MONTH_OF_YEAR 9)");
- assertAST("sep", "(MONTH_OF_YEAR 9)");
- assertAST("sept", "(MONTH_OF_YEAR 9)");
- assertAST("october", "(MONTH_OF_YEAR 10)");
- assertAST("oct", "(MONTH_OF_YEAR 10)");
- assertAST("november", "(MONTH_OF_YEAR 11)");
- assertAST("nov", "(MONTH_OF_YEAR 11)");
- assertAST("december", "(MONTH_OF_YEAR 12)");
- assertAST("dec", "(MONTH_OF_YEAR 12)");
- assertAST("jan.", "(MONTH_OF_YEAR 1)");
- assertAST("feb.", "(MONTH_OF_YEAR 2)");
- assertAST("mar.", "(MONTH_OF_YEAR 3)");
- assertAST("apr.", "(MONTH_OF_YEAR 4)");
- assertAST("jun.", "(MONTH_OF_YEAR 6)");
- assertAST("jul.", "(MONTH_OF_YEAR 7)");
- assertAST("aug.", "(MONTH_OF_YEAR 8)");
- assertAST("sep.", "(MONTH_OF_YEAR 9)");
- assertAST("sept.", "(MONTH_OF_YEAR 9)");
- assertAST("oct.", "(MONTH_OF_YEAR 10)");
- assertAST("nov.", "(MONTH_OF_YEAR 11)");
- assertAST("dec.", "(MONTH_OF_YEAR 12)");
- }
-
- @Test
- public void day_of_week() throws Exception {
- _ruleName = "day_of_week";
-
- assertAST("sunday" , "(DAY_OF_WEEK 1)");
- assertAST("sundays" , "(DAY_OF_WEEK 1)");
- assertAST("sun" , "(DAY_OF_WEEK 1)");
- assertAST("sun." , "(DAY_OF_WEEK 1)");
- assertAST("monday" , "(DAY_OF_WEEK 2)");
- assertAST("mondays" , "(DAY_OF_WEEK 2)");
- assertAST("mon" , "(DAY_OF_WEEK 2)");
- assertAST("mon." , "(DAY_OF_WEEK 2)");
- assertAST("tuesday" , "(DAY_OF_WEEK 3)");
- assertAST("tuesdays" , "(DAY_OF_WEEK 3)");
- assertAST("tues" , "(DAY_OF_WEEK 3)");
- assertAST("tues." , "(DAY_OF_WEEK 3)");
- assertAST("tue" , "(DAY_OF_WEEK 3)");
- assertAST("tue." , "(DAY_OF_WEEK 3)");
- assertAST("wednesday" , "(DAY_OF_WEEK 4)");
- assertAST("wednesdays", "(DAY_OF_WEEK 4)");
- assertAST("wed" , "(DAY_OF_WEEK 4)");
- assertAST("wed." , "(DAY_OF_WEEK 4)");
- assertAST("thursday" , "(DAY_OF_WEEK 5)");
- assertAST("thursdays" , "(DAY_OF_WEEK 5)");
- assertAST("thur" , "(DAY_OF_WEEK 5)");
- assertAST("thur." , "(DAY_OF_WEEK 5)");
- assertAST("thu" , "(DAY_OF_WEEK 5)");
- assertAST("thu." , "(DAY_OF_WEEK 5)");
- assertAST("friday" , "(DAY_OF_WEEK 6)");
- assertAST("fridays" , "(DAY_OF_WEEK 6)");
- assertAST("fri" , "(DAY_OF_WEEK 6)");
- assertAST("fri." , "(DAY_OF_WEEK 6)");
- assertAST("saturday" , "(DAY_OF_WEEK 7)");
- assertAST("saturdays" , "(DAY_OF_WEEK 7)");
- assertAST("sat" , "(DAY_OF_WEEK 7)");
- assertAST("sat." , "(DAY_OF_WEEK 7)");
- }
-
- @Test
- public void named_relative_date() throws Exception {
- _ruleName = "named_relative_date";
-
- assertAST("today", "(RELATIVE_DATE (SEEK > by_day 0 day))");
- assertAST("now", "(RELATIVE_DATE (SEEK > by_day 0 day))");
- assertAST("tomorow" , "(RELATIVE_DATE (SEEK > by_day 1 day))");
- assertAST("tomorrow" , "(RELATIVE_DATE (SEEK > by_day 1 day))");
- assertAST("tommorow" , "(RELATIVE_DATE (SEEK > by_day 1 day))");
- assertAST("tommorrow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
- assertAST("yesterday", "(RELATIVE_DATE (SEEK < by_day 1 day))");
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/grammar/DateTimeGrammarTest.java b/src/test/java/com/joestelmach/natty/grammar/DateTimeGrammarTest.java
deleted file mode 100644
index 49d09f97..00000000
--- a/src/test/java/com/joestelmach/natty/grammar/DateTimeGrammarTest.java
+++ /dev/null
@@ -1,86 +0,0 @@
-package com.joestelmach.natty.grammar;
-
-import org.junit.Test;
-
-public class DateTimeGrammarTest extends AbstractGrammarTest {
-
- @Test
- public void date_time_alternative() throws Exception {
- _ruleName = "date_time_alternative";
-
- assertAST("this wed. or next at 5pm", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)))");
- assertAST("feb 28th or 2 days after", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 28))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 28))))))");
- assertAST("january fourth or the friday after", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 4))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 6) (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 4))))))");
- assertAST("10/10/2008 or 10/12/2008", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10) (YEAR_OF 2008))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 12) (YEAR_OF 2008))))");
- assertAST("next wed or thursday", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5)))))");
- assertAST("next wed, thurs, fri", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 6)))))");
- assertAST("next wed, thurs, or fri at 6pm", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 6))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)))");
- assertAST("10/10 or 12/30 or 10/15 at 5pm", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 30))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 15)) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)))");
- assertAST("monday to friday", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 6)))))");
- assertAST("1999-12-31 to tomorrow", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 31) (YEAR_OF 1999))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 day))))");
- assertAST("now to 2010-01-01", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 day))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 01) (DAY_OF_MONTH 01) (YEAR_OF 2010))))");
- assertAST("2009-03-10 9:00 to 11:00", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 03) (DAY_OF_MONTH 10) (YEAR_OF 2009)) (EXPLICIT_TIME (HOURS_OF_DAY 9) (MINUTES_OF_HOUR 00))) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 11) (MINUTES_OF_HOUR 00))))");
- assertAST("26 oct 10:00 am to 11:00 am", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 26)) (EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 00) am)) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 11) (MINUTES_OF_HOUR 00) am)))");
- assertAST("jan 1 to 2", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 1))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 2))))");
- assertAST("16:00 nov 6 to 17:00", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 11) (DAY_OF_MONTH 6)) (EXPLICIT_TIME (HOURS_OF_DAY 16) (MINUTES_OF_HOUR 00))) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 17) (MINUTES_OF_HOUR 00))))");
- assertAST("may 2nd to 5th", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 2))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 5))))");
- assertAST("6am dec 5 to 7am", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 5)) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am)) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 7) (MINUTES_OF_HOUR 0) am)))");
- assertAST("1/3 to 2/3", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 3))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 3))))");
- assertAST("2/3 to in 1 week", "(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 3))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 week))))");
- assertAST("first day of may to last day of may", "(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 5)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 5)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))))");
- }
-
-
- @Test
- public void date_time() throws Exception {
- _ruleName = "date_time";
-
- assertAST("seven years ago at 3pm", "(DATE_TIME (RELATIVE_DATE (SEEK < by_day 7 year)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) pm))");
- assertAST("1st oct in the year '89 1300 hours", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))");
- assertAST("1st oct in the year '89 at 1300 hours", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))");
- assertAST("1st oct in the year '89, 13:00", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))");
- assertAST("1st oct in the year '89,13:00", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))");
- assertAST("1st oct in the year '89, at 13:00", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))");
- assertAST("3am on oct 1st 2010", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))");
- assertAST("3am, october first 2010", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))");
- assertAST("3am,october first 2010", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))");
- assertAST("3am, on october first 2010", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))");
- assertAST("3am october first 2010", "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))");
- assertAST("next wed. at 5pm", "(DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm))");
- assertAST("3 days after next wed", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 3 (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))))))");
- assertAST("the sunday after next wed", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 1) (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))))))");
- assertAST("two days after today", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 day)))");
- assertAST("two days from today", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 day)))");
- assertAST("3 sundays after next wed", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 3 (DAY_OF_WEEK 1) (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))))))");
- assertAST("the day after next", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 day)))");
- assertAST("the week after next", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 week)))");
- assertAST("the month after next", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 month)))");
- assertAST("the year after next", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 year)))");
- assertAST("wed of the week after next", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 week) (EXPLICIT_SEEK (DAY_OF_WEEK 4))))");
- assertAST("the 28th of the month after next", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 month) (EXPLICIT_SEEK (DAY_OF_MONTH 28))))");
- assertAST("6 in the morning", "(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am))");
- assertAST("4 in the afternoon", "(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 4) (MINUTES_OF_HOUR 0) pm))");
- assertAST("monday 6 in the morning", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am))");
- assertAST("monday 4 in the afternoon", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2))) (EXPLICIT_TIME (HOURS_OF_DAY 4) (MINUTES_OF_HOUR 0) pm))");
- assertAST("monday 9 in the evening", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2))) (EXPLICIT_TIME (HOURS_OF_DAY 9) (MINUTES_OF_HOUR 0) pm))");
- assertAST("this morning", "(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am))");
- assertAST("this afternoon", "(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm))");
- assertAST("final thursday in april", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 4)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5))))");
- assertAST("final thurs in sep", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5))))");
- assertAST("tomorrow @ noon", "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 day)) (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm))");
- assertAST("6 hours ago", "(DATE_TIME (RELATIVE_TIME (SEEK < by_day 6 hour)))");
- assertAST("10 hrs before noon", "(DATE_TIME (RELATIVE_TIME (SEEK < by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)) 10 hour)))");
- assertAST("10 hr before midnight", "(DATE_TIME (RELATIVE_TIME (SEEK < by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)) 10 hour)))");
- assertAST("5 hours after noon", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)) 5 hour)))");
- assertAST("5 hours after midnight", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)) 5 hour)))");
- assertAST("in 5 seconds", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day 5 second)))");
- assertAST("in 5 minutes", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day 5 minute)))");
- assertAST("in 5 hours", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day 5 hour)))");
- assertAST("4 secs from now", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 second)))");
- assertAST("4 sec from now", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 second)))");
- assertAST("4 minutes from now", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 minute)))");
- assertAST("4 mins from now", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 minute)))");
- assertAST("4 min from now", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 minute)))");
- assertAST("4 hours from now", "(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 hour)))");
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/grammar/HolidayGrammarTest.java b/src/test/java/com/joestelmach/natty/grammar/HolidayGrammarTest.java
deleted file mode 100644
index fce221b4..00000000
--- a/src/test/java/com/joestelmach/natty/grammar/HolidayGrammarTest.java
+++ /dev/null
@@ -1,132 +0,0 @@
-package com.joestelmach.natty.grammar;
-
-import org.junit.Test;
-
-public class HolidayGrammarTest extends AbstractGrammarTest {
-
- @Test
- public void names() throws Exception {
- _ruleName = "holiday_name";
-
- assertAST("april fool's day", "APRIL_FOOLS_DAY");
- assertAST("april fools day", "APRIL_FOOLS_DAY");
- assertAST("april fool day", "APRIL_FOOLS_DAY");
-
- assertAST("black friday", "BLACK_FRIDAY");
- assertAST("black fri", "BLACK_FRIDAY");
- assertAST("black fri.", "BLACK_FRIDAY");
-
- assertAST("christmas", "CHRISTMAS");
- assertAST("christmas day", "CHRISTMAS");
-
- assertAST("christmas eve", "CHRISTMAS_EVE");
- assertAST("christmas eve.", "CHRISTMAS_EVE");
- assertAST("christmas evening", "CHRISTMAS_EVE");
-
- assertAST("columbus day", "COLUMBUS_DAY");
-
- assertAST("earth day", "EARTH_DAY");
-
- assertAST("easter", "EASTER");
- assertAST("easter day", "EASTER");
- assertAST("easter sunday", "EASTER");
-
- assertAST("father's day", "FATHERS_DAY");
- assertAST("fathers day", "FATHERS_DAY");
-
- assertAST("flag day", "FLAG_DAY");
-
- assertAST("good friday", "GOOD_FRIDAY");
- assertAST("good fri", "GOOD_FRIDAY");
- assertAST("good fri.", "GOOD_FRIDAY");
-
- assertAST("groundhog day", "GROUNDHOG_DAY");
- assertAST("groundhogs day", "GROUNDHOG_DAY");
- assertAST("groundhog's day", "GROUNDHOG_DAY");
-
- assertAST("halloween", "HALLOWEEN");
- assertAST("haloween", "HALLOWEEN");
- assertAST("halloween day", "HALLOWEEN");
-
- assertAST("independence day", "INDEPENDENCE_DAY");
-
- assertAST("kwanzaa", "KWANZAA");
- assertAST("kwanza", "KWANZAA");
- assertAST("kwanzaa day", "KWANZAA");
-
- assertAST("labor day", "LABOR_DAY");
-
- assertAST("martin luther king day", "MLK_DAY");
- assertAST("martin luther king jr.'s day", "MLK_DAY");
- assertAST("martin luther king jr. day", "MLK_DAY");
- assertAST("martin luther king jr day", "MLK_DAY");
- assertAST("mlk day", "MLK_DAY");
-
- assertAST("memorial day", "MEMORIAL_DAY");
-
- assertAST("memorial day", "MEMORIAL_DAY");
-
- assertAST("mothers day", "MOTHERS_DAY");
- assertAST("mother's day", "MOTHERS_DAY");
-
- assertAST("new year's day", "NEW_YEARS_DAY");
- assertAST("new years day", "NEW_YEARS_DAY");
- assertAST("new years", "NEW_YEARS_DAY");
-
- assertAST("new year's eve", "NEW_YEARS_EVE");
- assertAST("new years eve", "NEW_YEARS_EVE");
- assertAST("new years eve.", "NEW_YEARS_EVE");
-
- assertAST("patriot day", "PATRIOT_DAY");
-
- assertAST("president's day", "PRESIDENTS_DAY");
- assertAST("presidents day", "PRESIDENTS_DAY");
- assertAST("president day", "PRESIDENTS_DAY");
-
- assertAST("st. patricks day", "ST_PATRICKS_DAY");
- assertAST("st patrick's day", "ST_PATRICKS_DAY");
- assertAST("saint patrick's day", "ST_PATRICKS_DAY");
- assertAST("saint paddy's day", "ST_PATRICKS_DAY");
- assertAST("saint paddys day", "ST_PATRICKS_DAY");
-
- assertAST("tax day", "TAX_DAY");
-
- assertAST("thanksgiving", "THANKSGIVING");
- assertAST("thanksgiving day", "THANKSGIVING");
-
- assertAST("election day", "ELECTION_DAY");
-
- assertAST("valentine's day", "VALENTINES_DAY");
- assertAST("valentines day", "VALENTINES_DAY");
- assertAST("valentine day", "VALENTINES_DAY");
-
- assertAST("veterans day", "VETERANS_DAY");
- assertAST("veteran's day", "VETERANS_DAY");
- assertAST("veteran day", "VETERANS_DAY");
- }
-
- @Test
- public void statments() throws Exception {
- _ruleName = "holiday";
-
- assertAST("april fool's day", "(SEEK > by_day 1 APRIL_FOOLS_DAY)");
-
- assertAST("next christmas", "(SEEK > by_week 1 CHRISTMAS)");
- assertAST("coming christmas", "(SEEK > by_day 1 CHRISTMAS)");
- assertAST("upcoming christmas", "(SEEK > by_day 1 CHRISTMAS)");
-
- assertAST("last halloween", "(SEEK < by_week 1 HALLOWEEN)");
- assertAST("past halloween", "(SEEK < by_day 1 HALLOWEEN)");
-
- assertAST("in three christmases", "(SEEK > by_day 3 CHRISTMAS)");
-
- assertAST("three christmases from now", "(SEEK > by_day 3 CHRISTMAS)");
- assertAST("3 christmases ago", "(SEEK < by_day 3 CHRISTMAS)");
- assertAST("2 april fool's days ago", "(SEEK < by_day 2 APRIL_FOOLS_DAY)");
-
- assertAST("in 10 thanksgivings", "(SEEK > by_day 10 THANKSGIVING)");
-
- assertAST("thanksgiving 2011", "(EXPLICIT_SEEK THANKSGIVING (YEAR_OF 2011))");
- assertAST("christmas, '95", "(EXPLICIT_SEEK CHRISTMAS (YEAR_OF 95))");
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/grammar/NumericGrammarTest.java b/src/test/java/com/joestelmach/natty/grammar/NumericGrammarTest.java
deleted file mode 100644
index 606dd15b..00000000
--- a/src/test/java/com/joestelmach/natty/grammar/NumericGrammarTest.java
+++ /dev/null
@@ -1,725 +0,0 @@
-package com.joestelmach.natty.grammar;
-
-import org.junit.Test;
-
-public class NumericGrammarTest extends AbstractGrammarTest {
-
- @Test
- public void int_00_to_23_optional_prefix() throws Exception {
- _ruleName = "int_00_to_23_optional_prefix";
-
- assertAST("00", "00");
- assertAST("01", "01");
- assertAST("02", "02");
- assertAST("03", "03");
- assertAST("04", "04");
- assertAST("05", "05");
- assertAST("06", "06");
- assertAST("07", "07");
- assertAST("08", "08");
- assertAST("09", "09");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- assertAST("13", "13");
- assertAST("14", "14");
- assertAST("15", "15");
- assertAST("16", "16");
- assertAST("17", "17");
- assertAST("18", "18");
- assertAST("19", "19");
- assertAST("20", "20");
- assertAST("21", "21");
- assertAST("22", "22");
- assertAST("23", "23");
- }
-
- @Test
- public void test_int_00_to_59_mandatory_prefix() throws Exception {
- _ruleName = "int_00_to_59_mandatory_prefix";
-
- assertAST("00", "00");
- assertAST("01", "01");
- assertAST("02", "02");
- assertAST("03", "03");
- assertAST("04", "04");
- assertAST("05", "05");
- assertAST("06", "06");
- assertAST("07", "07");
- assertAST("08", "08");
- assertAST("09", "09");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- assertAST("13", "13");
- assertAST("14", "14");
- assertAST("15", "15");
- assertAST("16", "16");
- assertAST("17", "17");
- assertAST("18", "18");
- assertAST("19", "19");
- assertAST("20", "20");
- assertAST("21", "21");
- assertAST("22", "22");
- assertAST("23", "23");
- assertAST("24", "24");
- assertAST("25", "25");
- assertAST("26", "26");
- assertAST("27", "27");
- assertAST("28", "28");
- assertAST("29", "29");
- assertAST("30", "30");
- assertAST("31", "31");
- assertAST("32", "32");
- assertAST("33", "33");
- assertAST("34", "34");
- assertAST("35", "35");
- assertAST("36", "36");
- assertAST("37", "37");
- assertAST("38", "38");
- assertAST("39", "39");
- assertAST("40", "40");
- assertAST("41", "41");
- assertAST("42", "42");
- assertAST("43", "43");
- assertAST("44", "44");
- assertAST("45", "45");
- assertAST("46", "46");
- assertAST("47", "47");
- assertAST("48", "48");
- assertAST("49", "49");
- assertAST("50", "50");
- assertAST("51", "51");
- assertAST("52", "52");
- assertAST("53", "53");
- assertAST("54", "54");
- assertAST("55", "55");
- assertAST("56", "56");
- assertAST("57", "57");
- assertAST("58", "58");
- assertAST("59", "59");
- /*
- "0" FAIL
- "1" FAIL
- "2" FAIL
- "3" FAIL
- "4" FAIL
- "5" FAIL
- "6" FAIL
- "7" FAIL
- "8" FAIL
- "9" FAIL
- "60" FAIL
- */
- }
-
- @Test
- public void test_int_00_to_99_mandatory_prefix() throws Exception {
- _ruleName = "int_00_to_99_mandatory_prefix";
-
- assertAST("00", "00");
- assertAST("01", "01");
- assertAST("02", "02");
- assertAST("03", "03");
- assertAST("04", "04");
- assertAST("05", "05");
- assertAST("06", "06");
- assertAST("07", "07");
- assertAST("08", "08");
- assertAST("09", "09");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- assertAST("13", "13");
- assertAST("14", "14");
- assertAST("15", "15");
- assertAST("16", "16");
- assertAST("17", "17");
- assertAST("18", "18");
- assertAST("19", "19");
- assertAST("20", "20");
- assertAST("21", "21");
- assertAST("22", "22");
- assertAST("23", "23");
- assertAST("24", "24");
- assertAST("25", "25");
- assertAST("26", "26");
- assertAST("27", "27");
- assertAST("28", "28");
- assertAST("29", "29");
- assertAST("30", "30");
- assertAST("31", "31");
- assertAST("32", "32");
- assertAST("33", "33");
- assertAST("34", "34");
- assertAST("35", "35");
- assertAST("36", "36");
- assertAST("37", "37");
- assertAST("38", "38");
- assertAST("39", "39");
- assertAST("40", "40");
- assertAST("41", "41");
- assertAST("42", "42");
- assertAST("43", "43");
- assertAST("44", "44");
- assertAST("45", "45");
- assertAST("46", "46");
- assertAST("47", "47");
- assertAST("48", "48");
- assertAST("49", "49");
- assertAST("50", "50");
- assertAST("51", "51");
- assertAST("52", "52");
- assertAST("53", "53");
- assertAST("54", "54");
- assertAST("55", "55");
- assertAST("56", "56");
- assertAST("57", "57");
- assertAST("58", "58");
- assertAST("59", "59");
- assertAST("60", "60");
- assertAST("61", "61");
- assertAST("62", "62");
- assertAST("63", "63");
- assertAST("64", "64");
- assertAST("65", "65");
- assertAST("66", "66");
- assertAST("67", "67");
- assertAST("68", "68");
- assertAST("69", "69");
- assertAST("70", "70");
- assertAST("71", "71");
- assertAST("72", "72");
- assertAST("73", "73");
- assertAST("74", "74");
- assertAST("75", "75");
- assertAST("76", "76");
- assertAST("77", "77");
- assertAST("78", "78");
- assertAST("79", "79");
- assertAST("80", "80");
- assertAST("81", "81");
- assertAST("82", "82");
- assertAST("83", "83");
- assertAST("84", "84");
- assertAST("85", "85");
- assertAST("86", "86");
- assertAST("87", "87");
- assertAST("88", "88");
- assertAST("89", "89");
- assertAST("90", "90");
- assertAST("91", "91");
- assertAST("92", "92");
- assertAST("93", "93");
- assertAST("94", "94");
- assertAST("95", "95");
- assertAST("96", "96");
- assertAST("97", "97");
- assertAST("98", "98");
- assertAST("99", "99");
- /*
- "0" FAIL
- "1" FAIL
- "2" FAIL
- "3" FAIL
- "4" FAIL
- "5" FAIL
- "6" FAIL
- "7" FAIL
- "8" FAIL
- "9" FAIL
- "100" FAIL
- */
- }
-
- @Test
- public void int_1_to_9() throws Exception {
- _ruleName = "int_1_to_9";
-
- assertAST("1", "1");
- assertAST("2", "2");
- assertAST("3", "3");
- assertAST("4", "4");
- assertAST("5", "5");
- assertAST("6", "6");
- assertAST("7", "7");
- assertAST("8", "8");
- assertAST("9", "9");
- /*
- FAIL:
- 0
- 00
- 01
- 02
- 03
- 04
- 05
- 06
- 07
- 08
- 09
- */
- }
-
- @Test
- public void int_01_to_12() throws Exception {
- _ruleName = "int_01_to_12";
-
- assertAST("01", "01");
- assertAST("02", "02");
- assertAST("03", "03");
- assertAST("04", "04");
- assertAST("05", "05");
- assertAST("06", "06");
- assertAST("07", "07");
- assertAST("08", "08");
- assertAST("09", "09");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- /*
- FAIL:
- 0
- 00
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- */
- }
-
-
- @Test
- public void int_13_to_23() throws Exception {
- _ruleName = "int_13_to_23";
-
- assertAST("13", "13");
- assertAST("14", "14");
- assertAST("15", "15");
- assertAST("16", "16");
- assertAST("17", "17");
- assertAST("18", "18");
- assertAST("19", "19");
- assertAST("20", "20");
- assertAST("21", "21");
- assertAST("22", "22");
- assertAST("23", "23");
- }
-
- @Test
- public void int_24_to_31() throws Exception {
- _ruleName = "int_24_to_31";
-
- assertAST("24", "24");
- assertAST("25", "25");
- assertAST("26", "26");
- assertAST("27", "27");
- assertAST("28", "28");
- assertAST("29", "29");
- assertAST("30", "30");
- assertAST("31", "31");
- }
-
- @Test
- public void int_32_to_59() throws Exception {
- _ruleName = "int_32_to_59";
-
- assertAST("32", "32");
- assertAST("33", "33");
- assertAST("34", "34");
- assertAST("35", "35");
- assertAST("36", "36");
- assertAST("37", "37");
- assertAST("38", "38");
- assertAST("39", "39");
- assertAST("40", "40");
- assertAST("41", "41");
- assertAST("42", "42");
- assertAST("43", "43");
- assertAST("44", "44");
- assertAST("45", "45");
- assertAST("46", "46");
- assertAST("47", "47");
- assertAST("48", "48");
- assertAST("49", "49");
- assertAST("50", "50");
- assertAST("51", "51");
- assertAST("52", "52");
- assertAST("53", "53");
- assertAST("54", "54");
- assertAST("55", "55");
- assertAST("56", "56");
- assertAST("57", "57");
- assertAST("58", "58");
- assertAST("59", "59");
- }
-
- @Test
- public void int_60_to_99() throws Exception {
- _ruleName = "int_60_to_99";
-
- assertAST("60", "60");
- assertAST("61", "61");
- assertAST("62", "62");
- assertAST("63", "63");
- assertAST("64", "64");
- assertAST("65", "65");
- assertAST("66", "66");
- assertAST("67", "67");
- assertAST("68", "68");
- assertAST("69", "69");
- assertAST("70", "70");
- assertAST("71", "71");
- assertAST("72", "72");
- assertAST("73", "73");
- assertAST("74", "74");
- assertAST("75", "75");
- assertAST("76", "76");
- assertAST("77", "77");
- assertAST("78", "78");
- assertAST("79", "79");
- assertAST("80", "80");
- assertAST("81", "81");
- assertAST("82", "82");
- assertAST("83", "83");
- assertAST("84", "84");
- assertAST("85", "85");
- assertAST("86", "86");
- assertAST("87", "87");
- assertAST("88", "88");
- assertAST("89", "89");
- assertAST("90", "90");
- assertAST("91", "91");
- assertAST("92", "92");
- assertAST("93", "93");
- assertAST("94", "94");
- assertAST("95", "95");
- assertAST("96", "96");
- assertAST("97", "97");
- assertAST("98", "98");
- assertAST("99", "99");
- }
-
- @Test
- public void int_01_to_12_optional_prefix() throws Exception {
- _ruleName = "int_01_to_12_optional_prefix";
-
- assertAST("01", "01");
- assertAST("1", "1");
- assertAST("02", "02");
- assertAST("2", "2");
- assertAST("03", "03");
- assertAST("3", "3");
- assertAST("04", "04");
- assertAST("4", "4");
- assertAST("05", "05");
- assertAST("5", "5");
- assertAST("06", "06");
- assertAST("6", "6");
- assertAST("07", "07");
- assertAST("7", "7");
- assertAST("08", "08");
- assertAST("8", "8");
- assertAST("09", "09");
- assertAST("9", "9");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- }
-
- @Test
- public void int_01_to_31_optional_prefix() throws Exception {
- _ruleName = "int_01_to_31_optional_prefix";
-
- assertAST("01", "01");
- assertAST("1", "1");
- assertAST("02", "02");
- assertAST("2", "2");
- assertAST("03", "03");
- assertAST("3", "3");
- assertAST("04", "04");
- assertAST("4", "4");
- assertAST("05", "05");
- assertAST("5", "5");
- assertAST("06", "06");
- assertAST("6", "6");
- assertAST("07", "07");
- assertAST("7", "7");
- assertAST("08", "08");
- assertAST("8", "8");
- assertAST("09", "09");
- assertAST("9", "9");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- assertAST("13", "13");
- assertAST("14", "14");
- assertAST("15", "15");
- assertAST("16", "16");
- assertAST("17", "17");
- assertAST("18", "18");
- assertAST("19", "19");
- assertAST("20", "20");
- assertAST("21", "21");
- assertAST("22", "22");
- assertAST("23", "23");
- assertAST("24", "24");
- assertAST("25", "25");
- assertAST("26", "26");
- assertAST("27", "27");
- assertAST("28", "28");
- assertAST("29", "29");
- assertAST("30", "30");
- assertAST("31", "31");
- }
-
- @Test
- public void int_four_digits() throws Exception {
- _ruleName = "int_four_digits";
-
- assertAST("0000", "0000");
- assertAST("0100", "0100");
- assertAST("0020", "0020");
- assertAST("0003", "0003");
- assertAST("9999", "9999");
- assertAST("5050", "5050");
- //"000" FAIL
- //"33" FAIL
- //"2" FAIL
- }
-
- @Test
- public void spelled_or_int_01_to_31_optional_prefix() throws Exception {
- _ruleName = "spelled_or_int_01_to_31_optional_prefix";
-
- assertAST("one", "1");
- assertAST("two", "2");
- assertAST("three", "3");
- assertAST("four", "4");
- assertAST("five", "5");
- assertAST("six", "6");
- assertAST("seven", "7");
- assertAST("eight", "8");
- assertAST("nine", "9");
- assertAST("ten", "10");
- assertAST("eleven", "11");
- assertAST("twelve", "12");
- assertAST("thirteen", "13");
- assertAST("fourteen", "14");
- assertAST("fifteen", "15");
- assertAST("sixteen", "16");
- assertAST("seventeen", "17");
- assertAST("eighteen", "18");
- assertAST("nineteen", "19");
- assertAST("twenty", "20");
- assertAST("twenty one", "21");
- assertAST("twenty-one", "21");
- assertAST("twenty two", "22");
- assertAST("twenty-two", "22");
- assertAST("twenty three", "23");
- assertAST("twenty-three", "23");
- assertAST("twenty four", "24");
- assertAST("twenty-four", "24");
- assertAST("twenty five", "25");
- assertAST("twenty-five", "25");
- assertAST("twenty six", "26");
- assertAST("twenty-six", "26");
- assertAST("twenty seven", "27");
- assertAST("twenty-seven", "27");
- assertAST("twenty-eight", "28");
- assertAST("twenty nine", "29");
- assertAST("twenty-nine", "29");
- assertAST("thirty", "30");
- assertAST("thirty one", "31");
- assertAST("thirty-one", "31");
- assertAST("01", "01");
- assertAST("1", "1");
- assertAST("02", "02");
- assertAST("2", "2");
- assertAST("03", "03");
- assertAST("3", "3");
- assertAST("04", "04");
- assertAST("4", "4");
- assertAST("05", "05");
- assertAST("5", "5");
- assertAST("06", "06");
- assertAST("6", "6");
- assertAST("07", "07");
- assertAST("7", "7");
- assertAST("08", "08");
- assertAST("8", "8");
- assertAST("09", "09");
- assertAST("9", "9");
- assertAST("10", "10");
- assertAST("11", "11");
- assertAST("12", "12");
- assertAST("13", "13");
- assertAST("14", "14");
- assertAST("15", "15");
- assertAST("16", "16");
- assertAST("17", "17");
- assertAST("18", "18");
- assertAST("19", "19");
- assertAST("20", "20");
- assertAST("21", "21");
- assertAST("22", "22");
- assertAST("23", "23");
- assertAST("24", "24");
- assertAST("25", "25");
- assertAST("26", "26");
- assertAST("27", "27");
- assertAST("28", "28");
- assertAST("29", "29");
- assertAST("30", "30");
- assertAST("31", "31");
- //assertAST("zero", FAIL
- }
-
- @Test
- public void spelled_or_int_optional_prefix() throws Exception {
- _ruleName = "spelled_or_int_optional_prefix";
-
- assertAST("1", "1");
- assertAST("01", "01");
- assertAST("60", "60");
- assertAST("99", "99");
- assertAST("one", "1");
- assertAST("two", "2");
- //"00" FAIL
- //"0" FAIL
- //"zero" FAIL
- }
-
- @Test
- public void spelled_one_to_thirty_one() throws Exception {
- _ruleName = "spelled_one_to_thirty_one";
-
- assertAST("one", "1");
- assertAST("two", "2");
- assertAST("three", "3");
- assertAST("four", "4");
- assertAST("five", "5");
- assertAST("six", "6");
- assertAST("seven", "7");
- assertAST("eight", "8");
- assertAST("nine", "9");
- assertAST("ten", "10");
- assertAST("eleven", "11");
- assertAST("twelve", "12");
- assertAST("thirteen", "13");
- assertAST("fourteen", "14");
- assertAST("fifteen", "15");
- assertAST("sixteen", "16");
- assertAST("seventeen", "17");
- assertAST("eighteen", "18");
- assertAST("nineteen", "19");
- assertAST("twenty", "20");
- assertAST("twenty one", "21");
- assertAST("twenty-one", "21");
- assertAST("twenty two", "22");
- assertAST("twenty-two", "22");
- assertAST("twenty three", "23");
- assertAST("twenty-three", "23");
- assertAST("twenty four", "24");
- assertAST("twenty-four", "24");
- assertAST("twenty five", "25");
- assertAST("twenty-five", "25");
- assertAST("twenty six", "26");
- assertAST("twenty-six", "26");
- assertAST("twenty seven", "27");
- assertAST("twenty-seven", "27");
- assertAST("twenty-eight", "28");
- assertAST("twenty nine", "29");
- assertAST("twenty-nine", "29");
- assertAST("thirty", "30");
- assertAST("thirty one", "31");
- assertAST("thirty-one", "31");
-
- //"zero" FAIL
- //"thirty two" FAIL
- //"thirty-two" FAIL
- }
-
- @Test
- public void spelled_first_to_thirty_first() throws Exception {
- _ruleName = "spelled_first_to_thirty_first";
-
- assertAST("first", "1");
- assertAST("1st", "1");
- assertAST("second", "2");
- assertAST("2nd", "2");
- assertAST("third", "3");
- assertAST("3rd", "3");
- assertAST("fourth", "4");
- assertAST("4th", "4");
- assertAST("fifth", "5");
- assertAST("5th", "5");
- assertAST("sixth", "6");
- assertAST("6th", "6");
- assertAST("seventh", "7");
- assertAST("7th", "7");
- assertAST("eighth", "8");
- assertAST("8th", "8");
- assertAST("ninth", "9");
- assertAST("9th", "9");
- assertAST("tenth", "10");
- assertAST("10th", "10");
- assertAST("eleventh", "11");
- assertAST("11th", "11");
- assertAST("twelfth", "12");
- assertAST("12th", "12");
- assertAST("thirteenth", "13");
- assertAST("13th", "13");
- assertAST("fourteenth", "14");
- assertAST("14th", "14");
- assertAST("fifteenth", "15");
- assertAST("15th", "15");
- assertAST("sixteenth", "16");
- assertAST("16th", "16");
- assertAST("seventeenth", "17");
- assertAST("17th", "17");
- assertAST("eighteenth", "18");
- assertAST("18th", "18");
- assertAST("nineteenth", "19");
- assertAST("19th", "19");
- assertAST("twentieth", "20");
- assertAST("20th", "20");
- assertAST("twenty-first", "21");
- assertAST("twenty first", "21");
- assertAST("21st", "21");
- assertAST("twenty-second", "22");
- assertAST("twenty second", "22");
- assertAST("22nd", "22");
- assertAST("twenty-third", "23");
- assertAST("twenty third", "23");
- assertAST("23rd", "23");
- assertAST("twenty-fourth", "24");
- assertAST("twenty fourth", "24");
- assertAST("24th", "24");
- assertAST("twenty-fifth", "25");
- assertAST("twenty fifth", "25");
- assertAST("25th", "25");
- assertAST("twenty-sixth", "26");
- assertAST("twenty sixth", "26");
- assertAST("26th", "26");
- assertAST("twenty-seventh", "27");
- assertAST("twenty seventh", "27");
- assertAST("27th", "27");
- assertAST("twenty-eighth", "28");
- assertAST("twenty eighth", "28");
- assertAST("28th", "28");
- assertAST("twenty-ninth", "29");
- assertAST("twenty ninth", "29");
- assertAST("29th", "29");
- assertAST("thirtieth", "30");
- assertAST("30th", "30");
- assertAST("thirty-first", "31");
- assertAST("thirty first", "31");
- assertAST("31st", "31");
- }
-}
diff --git a/src/test/java/com/joestelmach/natty/grammar/TimeGrammarTest.java b/src/test/java/com/joestelmach/natty/grammar/TimeGrammarTest.java
deleted file mode 100644
index b0eaba2f..00000000
--- a/src/test/java/com/joestelmach/natty/grammar/TimeGrammarTest.java
+++ /dev/null
@@ -1,189 +0,0 @@
-package com.joestelmach.natty.grammar;
-
-import org.junit.Test;
-
-public class TimeGrammarTest extends AbstractGrammarTest {
-
- @Test
- public void time_zone_abbreviation() throws Exception {
- _ruleName = "time_zone_abbreviation";
-
- assertAST("est", "America/New_York");
- assertAST("edt", "America/New_York");
- assertAST("et", "America/New_York");
- assertAST("pst", "America/Los_Angeles");
- assertAST("pdt", "America/Los_Angeles");
- assertAST("pt", "America/Los_Angeles");
- assertAST("cst", "America/Chicago");
- assertAST("cdt", "America/Chicago");
- assertAST("ct", "America/Chicago");
- assertAST("mst", "America/Denver");
- assertAST("mdt", "America/Denver");
- assertAST("mt", "America/Denver");
- assertAST("akst", "America/Anchorage");
- assertAST("akdt", "America/Anchorage");
- assertAST("akt", "America/Anchorage");
- assertAST("hast", "Pacific/Honolulu");
- assertAST("hadt" , "Pacific/Honolulu");
- assertAST("hat" , "Pacific/Honolulu");
- assertAST("hst", "Pacific/Honolulu");
- }
-
- @Test
- public void meridian_indicator() throws Exception {
- _ruleName = "meridian_indicator";
-
- assertAST("am", "am");
- assertAST("a.m.", "am");
- assertAST("a", "am");
- assertAST("pm", "pm");
- assertAST("p.m.", "pm");
- assertAST("p", "pm");
- }
-
- @Test
- public void minutes() throws Exception {
- _ruleName = "minutes";
-
- assertAST("00", "(MINUTES_OF_HOUR 00)");
- assertAST("01", "(MINUTES_OF_HOUR 01)");
- assertAST("02", "(MINUTES_OF_HOUR 02)");
- assertAST("03", "(MINUTES_OF_HOUR 03)");
- assertAST("04", "(MINUTES_OF_HOUR 04)");
- assertAST("05", "(MINUTES_OF_HOUR 05)");
- assertAST("06", "(MINUTES_OF_HOUR 06)");
- assertAST("07", "(MINUTES_OF_HOUR 07)");
- assertAST("08", "(MINUTES_OF_HOUR 08)");
- assertAST("09", "(MINUTES_OF_HOUR 09)");
- assertAST("10", "(MINUTES_OF_HOUR 10)");
- assertAST("11", "(MINUTES_OF_HOUR 11)");
- assertAST("12", "(MINUTES_OF_HOUR 12)");
- assertAST("13", "(MINUTES_OF_HOUR 13)");
- assertAST("14", "(MINUTES_OF_HOUR 14)");
- assertAST("15", "(MINUTES_OF_HOUR 15)");
- assertAST("16", "(MINUTES_OF_HOUR 16)");
- assertAST("17", "(MINUTES_OF_HOUR 17)");
- assertAST("18", "(MINUTES_OF_HOUR 18)");
- assertAST("19", "(MINUTES_OF_HOUR 19)");
- assertAST("20", "(MINUTES_OF_HOUR 20)");
- assertAST("21", "(MINUTES_OF_HOUR 21)");
- assertAST("22", "(MINUTES_OF_HOUR 22)");
- assertAST("23", "(MINUTES_OF_HOUR 23)");
- assertAST("24", "(MINUTES_OF_HOUR 24)");
- assertAST("25", "(MINUTES_OF_HOUR 25)");
- assertAST("26", "(MINUTES_OF_HOUR 26)");
- assertAST("27", "(MINUTES_OF_HOUR 27)");
- assertAST("28", "(MINUTES_OF_HOUR 28)");
- assertAST("29", "(MINUTES_OF_HOUR 29)");
- assertAST("30", "(MINUTES_OF_HOUR 30)");
- assertAST("31", "(MINUTES_OF_HOUR 31)");
- assertAST("32", "(MINUTES_OF_HOUR 32)");
- assertAST("33", "(MINUTES_OF_HOUR 33)");
- assertAST("34", "(MINUTES_OF_HOUR 34)");
- assertAST("35", "(MINUTES_OF_HOUR 35)");
- assertAST("36", "(MINUTES_OF_HOUR 36)");
- assertAST("37", "(MINUTES_OF_HOUR 37)");
- assertAST("38", "(MINUTES_OF_HOUR 38)");
- assertAST("39", "(MINUTES_OF_HOUR 39)");
- assertAST("40", "(MINUTES_OF_HOUR 40)");
- assertAST("41", "(MINUTES_OF_HOUR 41)");
- assertAST("42", "(MINUTES_OF_HOUR 42)");
- assertAST("43", "(MINUTES_OF_HOUR 43)");
- assertAST("44", "(MINUTES_OF_HOUR 44)");
- assertAST("45", "(MINUTES_OF_HOUR 45)");
- assertAST("46", "(MINUTES_OF_HOUR 46)");
- assertAST("47", "(MINUTES_OF_HOUR 47)");
- assertAST("48", "(MINUTES_OF_HOUR 48)");
- assertAST("49", "(MINUTES_OF_HOUR 49)");
- assertAST("50", "(MINUTES_OF_HOUR 50)");
- assertAST("51", "(MINUTES_OF_HOUR 51)");
- assertAST("52", "(MINUTES_OF_HOUR 52)");
- assertAST("53", "(MINUTES_OF_HOUR 53)");
- assertAST("54", "(MINUTES_OF_HOUR 54)");
- assertAST("55", "(MINUTES_OF_HOUR 55)");
- assertAST("56", "(MINUTES_OF_HOUR 56)");
- assertAST("57", "(MINUTES_OF_HOUR 57)");
- assertAST("58", "(MINUTES_OF_HOUR 58)");
- assertAST("59", "(MINUTES_OF_HOUR 59)");
- //assertAST("0", "FAIL ");
- //assertAST("1", "FAIL");
- //assertAST("2", "FAIL");
- //assertAST("3", "FAIL ");
- //assertAST("4", "FAIL");
- //assertAST("5", "FAIL");
- //assertAST("6", "FAIL");
- //assertAST("7", "FAIL");
- //assertAST("8", "FAIL");
- //assertAST("9", "FAIL");
- //"60" FAIL
- }
-
- @Test
- public void hours() throws Exception {
- _ruleName = "hours";
-
- assertAST("00", "(HOURS_OF_DAY 00)");
- assertAST("01", "(HOURS_OF_DAY 01)");
- assertAST("1" , "(HOURS_OF_DAY 1)");
- assertAST("02", "(HOURS_OF_DAY 02)");
- assertAST("2" , "(HOURS_OF_DAY 2)");
- assertAST("03", "(HOURS_OF_DAY 03)");
- assertAST("3" , "(HOURS_OF_DAY 3)");
- assertAST("04", "(HOURS_OF_DAY 04)");
- assertAST("4" , "(HOURS_OF_DAY 4)");
- assertAST("05", "(HOURS_OF_DAY 05)");
- assertAST("5" , "(HOURS_OF_DAY 5)");
- assertAST("06", "(HOURS_OF_DAY 06)");
- assertAST("6" , "(HOURS_OF_DAY 6)");
- assertAST("07", "(HOURS_OF_DAY 07)");
- assertAST("7" , "(HOURS_OF_DAY 7)");
- assertAST("08", "(HOURS_OF_DAY 08)");
- assertAST("8" , "(HOURS_OF_DAY 8)");
- assertAST("09", "(HOURS_OF_DAY 09)");
- assertAST("9" , "(HOURS_OF_DAY 9)");
- assertAST("10", "(HOURS_OF_DAY 10)");
- assertAST("11", "(HOURS_OF_DAY 11)");
- assertAST("12", "(HOURS_OF_DAY 12)");
- assertAST("13", "(HOURS_OF_DAY 13)");
- assertAST("14", "(HOURS_OF_DAY 14)");
- assertAST("15", "(HOURS_OF_DAY 15)");
- assertAST("16", "(HOURS_OF_DAY 16)");
- assertAST("17", "(HOURS_OF_DAY 17)");
- assertAST("18", "(HOURS_OF_DAY 18)");
- assertAST("19", "(HOURS_OF_DAY 19)");
- assertAST("20", "(HOURS_OF_DAY 20)");
- assertAST("21", "(HOURS_OF_DAY 21)");
- assertAST("22", "(HOURS_OF_DAY 22)");
- assertAST("23", "(HOURS_OF_DAY 23)");
- //"-1" FAIL
- //"24" FAIL
- }
-
- @Test
- public void explicit_time() throws Exception {
- _ruleName = "explicit_time";
-
- assertAST("0600h", "(EXPLICIT_TIME (HOURS_OF_DAY 06) (MINUTES_OF_HOUR 00))");
- assertAST("06:00h", "(EXPLICIT_TIME (HOURS_OF_DAY 06) (MINUTES_OF_HOUR 00))");
- assertAST("06:00 hours", "(EXPLICIT_TIME (HOURS_OF_DAY 06) (MINUTES_OF_HOUR 00))");
- assertAST("0000", "(EXPLICIT_TIME (HOURS_OF_DAY 00) (MINUTES_OF_HOUR 00))");
- assertAST("0700h", "(EXPLICIT_TIME (HOURS_OF_DAY 07) (MINUTES_OF_HOUR 00))");
- assertAST("6pm", "(EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)");
- assertAST("5:30 a.m.", "(EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 30) am)");
- assertAST("5", "(EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0))");
- assertAST("12:59", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 59))");
- assertAST("23:59", "(EXPLICIT_TIME (HOURS_OF_DAY 23) (MINUTES_OF_HOUR 59))");
- assertAST("00:00", "(EXPLICIT_TIME (HOURS_OF_DAY 00) (MINUTES_OF_HOUR 00))");
- assertAST("10:00am", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 00) am)");
- assertAST("10a", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 0) am)");
- assertAST("10am", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 0) am)");
- assertAST("10", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 0))");
- assertAST("8p", "(EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) pm)");
- assertAST("8pm", "(EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) pm)");
- assertAST("8 pm", "(EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) pm)");
- assertAST("noon", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)");
- assertAST("afternoon", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)");
- assertAST("midnight", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)");
- assertAST("mid-night", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)");
- }
-}
diff --git a/src/test/java/org/natty/AbstractTest.java b/src/test/java/org/natty/AbstractTest.java
new file mode 100644
index 00000000..be7953bc
--- /dev/null
+++ b/src/test/java/org/natty/AbstractTest.java
@@ -0,0 +1,119 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeEach;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Joe Stelmach
+ */
+public abstract class AbstractTest {
+ private static Calendar calendar;
+ protected static CalendarSource calendarSource;
+ protected static Parser parser;
+
+
+ public static void initCalendarAndParser() {
+ calendar = Calendar.getInstance();
+ parser = new Parser();
+ }
+
+ /**
+ * Resets the calendar source time before each test
+ */
+ @BeforeEach
+ public void before() {
+ calendarSource = new CalendarSource();
+ }
+
+ /**
+ * Parses the given value into a collection of dates
+ */
+ protected List parseCollection(Date referenceDate, String value) {
+ List dateGroup = parser.parse(value, referenceDate);
+ return dateGroup.isEmpty() ? new ArrayList() : dateGroup.get(0).getDates();
+ }
+
+ /**
+ * Parses the given value, asserting that one and only one date is produced.
+ */
+ protected Date parseSingleDate(String value, Date referenceDate) {
+ List dates = parseCollection(referenceDate, value);
+ assertThat(dates.size()).isEqualTo(1);
+ return dates.get(0);
+ }
+
+ /**
+ * Asserts that the given string value parses down to the given
+ * month, day, and year values.
+ */
+ protected void validateDate(Date referenceDate, String value, int month, int day, int year) {
+ Date date = parseSingleDate(value, referenceDate);
+ validateDate(date, month, day, year);
+ }
+
+ protected void validateDate(String value, int month, int day, int year) {
+ validateDate(new Date(), value, month, day, year);
+ }
+
+ /**
+ * Asserts that the given date contains the given attributes
+ */
+ protected void validateDate(Date date, int month, int day, int year) {
+ calendar.setTime(date);
+ assertThat(calendar.get(Calendar.MONTH)).isEqualTo(month - 1);
+ assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(day);
+ assertThat(calendar.get(Calendar.YEAR)).isEqualTo(year);
+ }
+
+ /**
+ * Asserts that the given string value parses down to the given
+ * hours, minutes, and seconds
+ */
+ protected void validateTime(Date referenceDate, String value, int hours, int minutes, int seconds) {
+ Date date = parseSingleDate(value, referenceDate);
+ validateTime(date, hours, minutes, seconds);
+ }
+
+ /**
+ * Asserts that the given date contains the given time attributes
+ */
+ protected void validateTime(Date date, int hours, int minutes, int seconds) {
+ calendar.setTime(date);
+ assertThat(calendar.get(Calendar.HOUR_OF_DAY)).isEqualTo(hours);
+ assertThat(calendar.get(Calendar.MINUTE)).isEqualTo(minutes);
+ assertThat(calendar.get(Calendar.SECOND)).isEqualTo(seconds);
+ }
+
+ /**
+ * Asserts that the given string value parses down to the given
+ * month, day, year, hours, minutes, and seconds
+ */
+ protected void validateDateTime(Date referenceDate, String value, int month, int day, int year,
+ int hours, int minutes, int seconds) {
+
+ Date date = parseSingleDate(value, referenceDate);
+ validateDateTime(date, month, day, year, hours, minutes, seconds);
+ }
+
+ /**
+ * Asserts that the given date contains the given attributes
+ */
+ protected void validateDateTime(Date date, int month, int day, int year,
+ int hours, int minutes, int seconds) {
+
+ calendar.setTime(date);
+
+ assertThat(calendar.get(Calendar.MONTH)).isEqualTo(month - 1);
+ assertThat(calendar.get(Calendar.DAY_OF_MONTH)).isEqualTo(day);
+ assertThat(calendar.get(Calendar.YEAR)).isEqualTo(year);
+ assertThat(calendar.get(Calendar.HOUR_OF_DAY)).isEqualTo(hours);
+ assertThat(calendar.get(Calendar.MINUTE)).isEqualTo(minutes);
+ assertThat(calendar.get(Calendar.SECOND)).isEqualTo(seconds);
+ }
+}
diff --git a/src/test/java/org/natty/CPANTest.java b/src/test/java/org/natty/CPANTest.java
new file mode 100644
index 00000000..1bb6d3f6
--- /dev/null
+++ b/src/test/java/org/natty/CPANTest.java
@@ -0,0 +1,39 @@
+package org.natty;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.BufferedReader;
+import java.io.InputStreamReader;
+import java.util.List;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+/**
+ * @author Joe Stelmach
+ */
+class CPANTest {
+
+ @Test
+ void sanityCheck() throws Exception {
+ BufferedReader reader = null;
+ try {
+ reader = new BufferedReader(new InputStreamReader(
+ CPANTest.class.getResourceAsStream("/cpan.txt")));
+
+ String value = null;
+ while ((value = reader.readLine()) != null) {
+ if (!value.trim().startsWith("#") && !value.trim().isEmpty()) {
+ Parser parser = new Parser();
+ List groups = parser.parse(value);
+ assertThat(groups).hasSize(1);
+ assertThat(groups.get(0).getDates()).isNotEmpty();
+ }
+ }
+ } finally {
+ if (reader != null) {
+ reader.close();
+ }
+ }
+ }
+}
diff --git a/src/test/java/org/natty/DateTest.java b/src/test/java/org/natty/DateTest.java
new file mode 100644
index 00000000..a64bc29b
--- /dev/null
+++ b/src/test/java/org/natty/DateTest.java
@@ -0,0 +1,431 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.text.DateFormat;
+import java.util.*;
+import java.util.Map.Entry;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+
+/**
+ * Runs the parser through the various date formats
+ *
+ * @author Joe Stelmach
+ */
+class DateTest extends AbstractTest {
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ @Test
+ void testFormal() {
+ validateDate("1978-01-28", 1, 28, 1978);
+ validateDate("2009-10-10", 10, 10, 2009);
+ validateDate("1980-1-2", 1, 2, 1980);
+ validateDate("12/12/12", 12, 12, 2012);
+ validateDate("3/4", 3, 4, Calendar.getInstance().get(Calendar.YEAR));
+ validateDate("sun, 11/21/2010", 11, 21, 2010);
+ validateDate("in october 2006", 10, 1, 2006);
+ validateDate("feb 1979", 2, 1, 1979);
+ validateDate("jan '80", 1, 1, 1980);
+ validateDate("2006-Jun-16", 6, 16, 2006);
+ validateDate("28-Feb-2010", 2, 28, 2010);
+ validateDate("9-Apr", 4, 9, Calendar.getInstance().get(Calendar.YEAR));
+ validateDate("jan 10, '00", 1, 10, 2000);
+ }
+
+ @Test
+ void testRelaxed() {
+ validateDate("oct 1, 1980", 10, 1, 1980);
+ validateDate("oct. 1, 1980", 10, 1, 1980);
+ validateDate("oct 1,1980", 10, 1, 1980);
+ validateDate("1st oct in the year '89", 10, 1, 1989);
+ validateDate("thirty first of december '80", 12, 31, 1980);
+ validateDate("the first of december in the year 1980", 12, 1, 1980);
+ validateDate("the 2 of february in the year 1980", 2, 2, 1980);
+ validateDate("the 2nd of february in the year 1980", 2, 2, 1980);
+ validateDate("the second of february in the year 1980", 2, 2, 1980);
+ validateDate("jan. 2nd", 1, 2, Calendar.getInstance().get(Calendar.YEAR));
+ validateDate("sun, nov 21 2010", 11, 21, 2010);
+ validateDate("Second Monday in October 2017", 10, 9, 2017);
+ validateDate("2nd thursday in sept. '02", 9, 12, 2002);
+ }
+
+ @Test
+ void testExplicitRelative() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/28/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "final thursday in april", 4, 28, 2011);
+ validateDate(reference, "final thurs in sep", 9, 29, 2011);
+ validateDate(reference, "4th february ", 2, 4, 2011);
+ }
+
+ @Test
+ void testRelative() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/28/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "yesterday", 2, 27, 2011);
+ validateDate(reference, "tomorrow", 3, 1, 2011);
+ validateDate(reference, "tmr", 3, 1, 2011);
+ validateDate(reference, "in 3 days", 3, 3, 2011);
+ validateDate(reference, "3 days ago", 2, 25, 2011);
+ validateDate(reference, "in 3 weeks", 3, 21, 2011);
+ validateDate(reference, "four weeks ago", 1, 31, 2011);
+ validateDate(reference, "in 3 months", 5, 28, 2011);
+ validateDate(reference, "three months ago", 11, 28, 2010);
+ validateDate(reference, "in 3 years", 2, 28, 2014);
+ validateDate(reference, "seven years ago", 2, 28, 2004);
+ validateDate(reference, "60 years ago", 2, 28, 1951);
+ validateDate(reference, "32 days ago", 1, 27, 2011);
+ validateDate(reference, "320 days ago", 4, 14, 2010);
+ validateDate(reference, "1200 days ago", 11, 16, 2007);
+ validateDate(reference, "365 days from now", 2, 28, 2012);
+ validateDate(reference, "100 months now", 6, 28, 2019);
+ validateDate(reference, "100 years from now", 2, 28, 2111);
+ validateDate(reference, "next monday", 3, 7, 2011);
+ validateDate(reference, "next mon", 3, 7, 2011);
+ validateDate(reference, "4 mondays from now", 3, 28, 2011);
+ validateDate(reference, "4 mondays from today", 3, 28, 2011);
+ validateDate(reference, "next weekend", 3, 12, 2011);
+ validateDate(reference, "six mondays ago", 1, 17, 2011);
+ validateDate(reference, "last monday", 2, 21, 2011);
+ validateDate(reference, "last mon", 2, 21, 2011);
+ validateDate(reference, "this past mon", 2, 21, 2011);
+ validateDate(reference, "this coming mon", 3, 7, 2011);
+ validateDate(reference, "this upcoming mon", 3, 7, 2011);
+ validateDate(reference, "next thurs", 3, 10, 2011);
+ validateDate(reference, "next month", 3, 28, 2011);
+ validateDate(reference, "last month", 1, 28, 2011);
+ validateDate(reference, "next week", 3, 7, 2011);
+ validateDate(reference, "last week", 2, 21, 2011);
+ validateDate(reference, "next year", 2, 28, 2012);
+ validateDate(reference, "last year", 2, 28, 2010);
+ validateDate(reference, "tues this week", 3, 1, 2011);
+ validateDate(reference, "tuesday this week", 3, 1, 2011);
+ validateDate(reference, "tuesday next week", 3, 8, 2011);
+ validateDate(reference, "this september", 9, 1, 2011);
+ validateDate(reference, "in a september", 9, 1, 2011);
+ validateDate(reference, "in an october", 10, 1, 2011);
+ validateDate(reference, "september", 9, 1, 2011);
+ validateDate(reference, "last september", 9, 1, 2010);
+ validateDate(reference, "next september", 9, 1, 2011);
+ validateDate(reference, "january", 1, 1, 2011);
+ validateDate(reference, "last january", 1, 1, 2011);
+ validateDate(reference, "next january", 1, 1, 2012);
+ validateDate(reference, "next february", 2, 1, 2012);
+ validateDate(reference, "last february", 2, 1, 2010);
+ validateDate(reference, "february ", 2, 1, 2011);
+ validateDate(reference, "in a year", 2, 28, 2012);
+ validateDate(reference, "in a week", 3, 7, 2011);
+ validateDate(reference, "the saturday after next", 3, 19, 2011);
+ validateDate(reference, "the monday after next", 3, 14, 2011);
+ validateDate(reference, "the monday after next monday", 3, 14, 2011);
+ validateDate(reference, "the monday before May 25", 5, 23, 2011);
+ validateDate(reference, "the 2nd monday before May 25", 5, 16, 2011);
+ validateDate(reference, "3 mondays after May 25", 6, 13, 2011);
+ validateDate(reference, "tuesday before last", 2, 15, 2011);
+ validateDate(reference, "a week from now", 3, 7, 2011);
+ validateDate(reference, "a month from today", 3, 28, 2011);
+ validateDate(reference, "a week after this friday", 3, 11, 2011);
+ validateDate(reference, "a week from this friday", 3, 11, 2011);
+ validateDate(reference, "two weeks from this friday", 3, 18, 2011);
+ validateDate(reference, "the second week after this friday", 3, 18, 2011);
+ validateDate(reference, "It's gonna snow! How about skiing tomorrow", 3, 1, 2011);
+ validateDate(reference, "A week on tuesday", 3, 8, 2011);
+ validateDate(reference, "A month ago", 1, 28, 2011);
+ validateDate(reference, "A week ago", 2, 21, 2011);
+ validateDate(reference, "A year ago", 2, 28, 2010);
+ validateDate(reference, "this month", 2, 28, 2011);
+ validateDate(reference, "current month", 2, 28, 2011);
+ validateDate(reference, "current year", 2, 28, 2011);
+ validateDate(reference, "first monday in 1 month", 3, 7, 2011);
+ validateDate(reference, "first monday of month in 1 month", 3, 7, 2011);
+ validateDate(reference, "first monday of 1 month", 3, 7, 2011);
+ validateDate(reference, "first monday in 2 months", 4, 4, 2011);
+ validateDate(reference, "first monday of 2 months", 4, 4, 2011);
+ validateDate(reference, "first monday of month 2 months", 4, 4, 2011);
+ validateDate(reference, "first monday of month in 2 months", 4, 4, 2011);
+ validateDate(reference, "first monday in 3 months", 5, 2, 2011);
+ validateDate(reference, "first monday of 3 months", 5, 2, 2011);
+ validateDate(reference, "first monday of month in 3 months", 5, 2, 2011);
+ validateDate(reference, "1 year 9 months from now", 11, 28, 2012);
+ validateDate(reference, "1 year 9 months 1 day from now", 11, 29, 2012);
+ validateDate(reference, "2 years 4 months ago", 10, 28, 2008);
+ validateDate(reference, "2 years 4 months 5 days ago", 10, 23, 2008);
+ }
+
+ @Test
+ void testRange() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("1/02/2011");
+ calendarSource = new CalendarSource(reference);
+
+ List dates = parseCollection(reference, "monday to friday");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 3, 2011);
+ validateDate(dates.get(1), 1, 7, 2011);
+
+ dates = parseCollection(reference, "1999-12-31 to tomorrow");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 12, 31, 1999);
+ validateDate(dates.get(1), 1, 3, 2011);
+
+ dates = parseCollection(reference, "now to 2010-01-01");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 1, 1, 2010);
+
+ dates = parseCollection(reference, "jan 1 to 2");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 1, 2011);
+ validateDate(dates.get(1), 1, 2, 2011);
+
+ dates = parseCollection(reference, "may 2nd to 5th");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 5, 2, 2011);
+ validateDate(dates.get(1), 5, 5, 2011);
+
+ dates = parseCollection(reference, "1/3 to 2/3");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 3, 2011);
+ validateDate(dates.get(1), 2, 3, 2011);
+
+ dates = parseCollection(reference, "2/3 to in one week");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 2, 3, 2011);
+ validateDate(dates.get(1), 1, 9, 2011);
+
+ dates = parseCollection(reference, "first day of may to last day of may");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 5, 1, 2011);
+ validateDate(dates.get(1), 5, 31, 2011);
+
+ dates = parseCollection(reference, "feb 28th or 2 days after");
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 28, 2011);
+ validateDate(dates.get(1), 3, 2, 2011);
+
+ dates = parseCollection(reference, "tomorrow at 10 and monday at 11");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 3, 2011);
+ validateDate(dates.get(1), 1, 3, 2011);
+
+ dates = parseCollection(reference, "tomorrow at 10 through tues at 11");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 3, 2011);
+ validateDate(dates.get(1), 1, 4, 2011);
+
+ dates = parseCollection(reference, "first day of 2009 to last day of 2009");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 1, 2009);
+ validateDate(dates.get(1), 12, 31, 2009);
+
+ dates = parseCollection(reference, "first to last day of 2008");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 1, 2008);
+ validateDate(dates.get(1), 12, 31, 2008);
+
+ dates = parseCollection(reference, "first to last day of september");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 9, 1, 2011);
+ validateDate(dates.get(1), 9, 30, 2011);
+
+ dates = parseCollection(reference, "first to last day of this september");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 9, 1, 2011);
+ validateDate(dates.get(1), 9, 30, 2011);
+
+ dates = parseCollection(reference, "first to last day of 2 septembers ago");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 9, 1, 2009);
+ validateDate(dates.get(1), 9, 30, 2009);
+
+ dates = parseCollection(reference, "first to last day of 2 septembers from now");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 9, 1, 2012);
+ validateDate(dates.get(1), 9, 30, 2012);
+
+ dates = parseCollection(reference, "for 5 days");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 1, 7, 2011);
+
+ dates = parseCollection(reference, "for ten months");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 11, 2, 2011);
+
+ dates = parseCollection(reference, "for twenty-five years");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 1, 2, 2036);
+
+ dates = parseCollection(reference, "2 and 4 months");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 3, 2, 2011);
+ validateDate(dates.get(1), 5, 2, 2011);
+
+ dates = parseCollection(reference, "in 2 to 4 months");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 3, 2, 2011);
+ validateDate(dates.get(1), 5, 2, 2011);
+
+ dates = parseCollection(reference, "for 2 to 4 months");
+ assertThat(dates).hasSize(3);
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 3, 2, 2011);
+ validateDate(dates.get(2), 5, 2, 2011);
+
+ dates = parseCollection(reference, "next 2 to 4 months");
+ assertThat(dates).hasSize(3);
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 3, 2, 2011);
+ validateDate(dates.get(2), 5, 2, 2011);
+
+ dates = parseCollection(reference, "2 to 4 months from now");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 3, 2, 2011);
+ validateDate(dates.get(1), 5, 2, 2011);
+
+ dates = parseCollection(reference, "last 2 to 4 months");
+ assertThat(dates).hasSize(3);
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 11, 2, 2010);
+ validateDate(dates.get(2), 9, 2, 2010);
+
+ dates = parseCollection(reference, "past 2 to 4 months");
+ assertThat(dates).hasSize(3);
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 11, 2, 2010);
+ validateDate(dates.get(2), 9, 2, 2010);
+
+ dates = parseCollection(reference, "2 to 4 months ago");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 11, 2, 2010);
+ validateDate(dates.get(1), 9, 2, 2010);
+
+ dates = parseCollection(reference, "2 or 3 days ago");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 12, 31, 2010);
+ validateDate(dates.get(1), 12, 30, 2010);
+
+ dates = parseCollection(reference, "1 to 2 days");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 1, 3, 2011);
+ validateDate(dates.get(1), 1, 4, 2011);
+
+ dates = parseCollection(reference, "I want to go shopping in Knoxville, TN in the next five to six months.");
+ assertThat(dates).hasSize(3);
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 6, 2, 2011);
+ validateDate(dates.get(2), 7, 2, 2011);
+
+ dates = parseCollection(reference, "I want to watch the fireworks in the next two to three months.");
+ assertThat(dates).hasSize(3);
+ validateDate(dates.get(0), 1, 2, 2011);
+ validateDate(dates.get(1), 3, 2, 2011);
+ validateDate(dates.get(2), 4, 2, 2011);
+
+ dates = parseCollection(reference, "september 7th something");
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 7, 2011);
+
+ dates = parseCollection(reference, "september 7th something happened here");
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 7, 2011);
+
+ dates = parseCollection(reference, "bla bla bla 2 and 4 month");
+ assertThat(dates).hasSize(2);
+
+ validateDate(dates.get(0), 3, 2, 2011);
+ validateDate(dates.get(1), 5, 2, 2011);
+ }
+
+ // https://github.org/natty/issues/38
+ @Test
+ void testRelativeDateDifferentTimezone() {
+ // Prepare
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ Parser parser = new Parser(TimeZone.getTimeZone("US/Pacific"));
+ // 2012, June 3, Sunday, 1 a.m. in US/Eastern GMT -4
+ // Same time as
+ // 2012, June 2, Saturday, 10 p.m. in US/Pacific GMT -7
+ Calendar earlySunday = new GregorianCalendar(2012, 5, 3, 1, 0);
+ calendarSource = new CalendarSource(earlySunday.getTime());
+
+ // Run
+ Date result = parser.parse("Sunday at 10am", earlySunday.getTime()).get(0).getDates().get(0);
+
+ // Validate
+ // Result should be June 3, 2012
+ validateDate(result, 6, 3, 2012);
+
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ }
+
+ public static void main(String[] args) {
+
+ String value = "easter '06";
+
+ Parser parser = new Parser();
+ List groups = parser.parse(value);
+ for (DateGroup group : groups) {
+ System.out.println(value);
+ System.out.println(group.getSyntaxTree().toStringTree());
+ System.out.println("line: " + group.getLine() + ", column: " + group.getPosition());
+ System.out.println(group.getText());
+ System.out.println(group.getDates());
+ System.out.println("is time inferred: " + group.isTimeInferred());
+ System.out.println("is recurring: " + group.isRecurring());
+ System.out.println("recurs until: " + group.getRecursUntil());
+
+ System.out.println("\n** Parse Locations **");
+ for (Entry> entry : group.getParseLocations().entrySet()) {
+ for (ParseLocation loc : entry.getValue()) {
+ System.out.println(loc.getRuleName() + ": " + loc.getText());
+ }
+ }
+
+ List conjunctionLocations = group.getParseLocations().get("conjunction");
+ if (conjunctionLocations != null) {
+ System.out.print("\nconjunctions: ");
+ for (ParseLocation location : conjunctionLocations) {
+ System.out.print(location.getText() + " ");
+ }
+ }
+ System.out.print("\n\n");
+ }
+ }
+}
diff --git a/src/test/java/org/natty/DateTimeTest.java b/src/test/java/org/natty/DateTimeTest.java
new file mode 100644
index 00000000..f9bebca1
--- /dev/null
+++ b/src/test/java/org/natty/DateTimeTest.java
@@ -0,0 +1,171 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Runs the parser through the various datetime formats
+ *
+ * @author Joe Stelmach
+ */
+class DateTimeTest extends AbstractTest {
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ @Test
+ void testSpecific() {
+ final LocalDateTime refDateTime = LocalDateTime.of(2012, 5, 19, 12, 0, 0);
+ Date reference = Timestamp.valueOf(refDateTime);
+ calendarSource = new CalendarSource(reference);
+
+ validateDateTime(reference, "1st oct in the year '89 1300 hours", 10, 1, 1989, 13, 0, 0);
+ validateDateTime(reference, "1st oct in the year '89 at 1300 hours", 10, 1, 1989, 13, 0, 0);
+ validateDateTime(reference, "1st oct in the year '89, 13:00", 10, 1, 1989, 13, 0, 0);
+ validateDateTime(reference, "1st oct in the year '89,13:00", 10, 1, 1989, 13, 0, 0);
+ validateDateTime(reference, "1st oct in the year '89, at 13:00", 10, 1, 1989, 13, 0, 0);
+ validateDateTime(reference, "3am on oct 1st 2010", 10, 1, 2010, 3, 0, 0);
+ validateDateTime(reference, "3am, october first 2010", 10, 1, 2010, 3, 0, 0);
+ validateDateTime(reference, "3am,october first 2010", 10, 1, 2010, 3, 0, 0);
+ validateDateTime(reference, "3am, on october first 2010", 10, 1, 2010, 3, 0, 0);
+ validateDateTime(reference, "3am october first 2010", 10, 1, 2010, 3, 0, 0);
+ validateDateTime(reference, "April 20, 10am", 4, 20, 2012, 10, 0, 0);
+ validateDateTime(reference, "April 20 10", 4, 20, 2012, 10, 0, 0);
+ validateDateTime(reference, "April 20 at 10 am", 4, 20, 2012, 10, 0, 0);
+ validateDateTime(reference, "Mar 16, 2015 3:33:39 PM", 3, 16, 2015, 15, 33, 39);
+ }
+
+ @Test
+ public void testRelative() {
+ final LocalDateTime refDateTime = LocalDateTime.of(2011, 2, 24, 0, 0, 0);
+ Date reference = Timestamp.valueOf(refDateTime);
+ calendarSource = new CalendarSource(reference);
+
+ validateDateTime(reference, "seven years ago at 3pm", 2, 24, 2004, 15, 0, 0);
+ validateDateTime(reference, "next wed. at 5pm", 3, 2, 2011, 17, 0, 0);
+ validateDateTime(reference, "3 days after next wed at 6a", 3, 5, 2011, 6, 0, 0);
+ validateDateTime(reference, "8pm on the sunday after next wed", 3, 6, 2011, 20, 0, 0);
+ validateDateTime(reference, "two days after today @ 6p", 2, 26, 2011, 18, 0, 0);
+ validateDateTime(reference, "two days from today @ 6p", 2, 26, 2011, 18, 0, 0);
+ validateDateTime(reference, "11:59 on 3 sundays after next wed", 3, 20, 2011, 11, 59, 0);
+ validateDateTime(reference, "the day after next 6pm", 2, 26, 2011, 18, 0, 0);
+ validateDateTime(reference, "the week after next 2a", 3, 10, 2011, 2, 0, 0);
+ validateDateTime(reference, "the month after next 0700", 4, 24, 2011, 7, 0, 0);
+ validateDateTime(reference, "the year after next @ midnight", 2, 24, 2013, 0, 0, 0);
+ validateDateTime(reference, "wed of the week after next in the evening", 3, 9, 2011, 19, 0, 0);
+ validateDateTime(reference, "the 28th of the month after next in the morning", 4, 28, 2011, 8, 0, 0);
+ validateDateTime(reference, "this morning", 2, 24, 2011, 8, 0, 0);
+ validateDateTime(reference, "this afternoon", 2, 24, 2011, 12, 0, 0);
+ validateDateTime(reference, "this evening", 2, 24, 2011, 19, 0, 0);
+ validateDateTime(reference, "today evening", 2, 24, 2011, 19, 0, 0);
+ validateDateTime(reference, "tomorrow evening", 2, 25, 2011, 19, 0, 0);
+ validateDateTime(reference, "friday evening", 2, 25, 2011, 19, 0, 0);
+ validateDateTime(reference, "monday 6 in the morning", 2, 28, 2011, 6, 0, 0);
+ validateDateTime(reference, "monday 4 in the afternoon", 2, 28, 2011, 16, 0, 0);
+ validateDateTime(reference, "monday 9 in the evening", 2, 28, 2011, 21, 0, 0);
+ validateDateTime(reference, "tomorrow @ noon", 2, 25, 2011, 12, 0, 0);
+ validateDateTime(reference, "Acknowledged. Let's meet at 9pm.", 2, 24, 2011, 21, 0, 0);
+ validateDateTime(reference, "tuesday,\u00A012:50 PM", 3, 1, 2011, 12, 50, 0);
+ validateDateTime(reference, "tonight at 6:30", 2, 24, 2011, 18, 30, 0);
+ validateDateTime(reference, "tonight at 6", 2, 24, 2011, 18, 0, 0);
+ validateDateTime(reference, "tonight at 2", 2, 25, 2011, 2, 0, 0);
+ validateDateTime(reference, "tonight at 4:59", 2, 25, 2011, 4, 59, 0);
+ validateDateTime(reference, "tonight at 5", 2, 24, 2011, 17, 0, 0);
+ validateDateTime(reference, "this evening at 5", 2, 24, 2011, 17, 0, 0);
+ validateDateTime(reference, "this evening at 2", 2, 25, 2011, 2, 0, 0);
+ validateDateTime(reference, "tomorrow evening at 5", 2, 25, 2011, 17, 0, 0);
+ validateDateTime(reference, "wed evening at 8:30", 3, 2, 2011, 20, 30, 0);
+ validateDateTime(reference, "750 minutes from now", 2, 24, 2011, 12, 30, 0);
+ validateDateTime(reference, "1500 minutes from now", 2, 25, 2011, 1, 0, 0);
+ }
+
+ @Test
+ public void testRange() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("6/12/2010");
+ calendarSource = new CalendarSource(reference);
+
+ List dates = parseCollection(reference, "2009-03-10 9:00 to 11:00");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 3, 10, 2009, 9, 0, 0);
+ validateDateTime(dates.get(1), 3, 10, 2009, 11, 0, 0);
+
+ dates = parseCollection(reference, "26 oct 10:00 am to 11:00 am");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 10, 26, 2010, 10, 0, 0);
+ validateDateTime(dates.get(1), 10, 26, 2010, 11, 0, 0);
+
+ dates = parseCollection(reference, "16:00 nov 6 to 17:00");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 11, 6, 2010, 16, 0, 0);
+ validateDateTime(dates.get(1), 11, 6, 2010, 17, 0, 0);
+
+ dates = parseCollection(reference, "6am dec 5 to 7am");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 12, 5, 2010, 6, 0, 0);
+ validateDateTime(dates.get(1), 12, 5, 2010, 7, 0, 0);
+
+ dates = parseCollection(reference, "3/3 21:00 to in 5 days");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 3, 3, 2010, 21, 0, 0);
+ validateDateTime(dates.get(1), 6, 17, 2010, 21, 0, 0);
+
+ dates = parseCollection(reference, "November 20 2 p.m. to 3 p.m");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 11, 20, 2010, 14, 0, 0);
+ validateDateTime(dates.get(1), 11, 20, 2010, 15, 0, 0);
+
+ dates = parseCollection(reference, "November 20 2 p.m. - 3 p.m.");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 11, 20, 2010, 14, 0, 0);
+ validateDateTime(dates.get(1), 11, 20, 2010, 15, 0, 0);
+ }
+
+ @Test
+ void testList() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("05/19/2012");
+ calendarSource = new CalendarSource(reference);
+
+ List dates =
+ parseCollection(reference, "June 25th at 9am and July 2nd at 10am and August 16th at 11am");
+ assertThat(dates).hasSize(3);
+ validateDateTime(dates.get(0), 6, 25, 2012, 9, 0, 0);
+ validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
+ validateDateTime(dates.get(2), 8, 16, 2012, 11, 0, 0);
+
+ dates = parseCollection(reference, "June 25th at 10am and July 2nd and August 16th");
+ assertThat(dates).hasSize(3);
+ validateDateTime(dates.get(0), 6, 25, 2012, 10, 0, 0);
+ validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
+ validateDateTime(dates.get(2), 8, 16, 2012, 10, 0, 0);
+
+ dates = parseCollection(reference, "June 25th and July 2nd at 10am and August 16th");
+ assertThat(dates).hasSize(3);
+ validateDateTime(dates.get(0), 6, 25, 2012, 10, 0, 0);
+ validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
+ validateDateTime(dates.get(2), 8, 16, 2012, 10, 0, 0);
+
+ dates = parseCollection(reference, "June 25th and July 2nd and August 16th at 10am");
+ assertThat(dates).hasSize(3);
+ validateDateTime(dates.get(0), 6, 25, 2012, 10, 0, 0);
+ validateDateTime(dates.get(1), 7, 2, 2012, 10, 0, 0);
+ validateDateTime(dates.get(2), 8, 16, 2012, 10, 0, 0);
+
+ dates = parseCollection(reference, "slept from 3:30 a.m. To 9:41 a.m. On April 10th");
+ assertThat(dates).hasSize(2);
+ validateDateTime(dates.get(0), 4, 10, 2012, 3, 30, 0);
+ validateDateTime(dates.get(1), 4, 10, 2012, 9, 41, 0);
+ }
+}
diff --git a/src/test/java/org/natty/IcsTest.java b/src/test/java/org/natty/IcsTest.java
new file mode 100644
index 00000000..5314878a
--- /dev/null
+++ b/src/test/java/org/natty/IcsTest.java
@@ -0,0 +1,153 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+
+public class IcsTest extends AbstractTest {
+
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ @Test
+ void testUpcomingSeason() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("5/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "spring", 3, 20, 2012);
+ validateDate(reference, "summer", 6, 21, 2011);
+ validateDate(reference, "fall", 9, 23, 2011);
+ validateDate(reference, "autumn", 9, 23, 2011);
+ validateDate(reference, "winter", 12, 22, 2011);
+ }
+
+ @Test
+ public void testUpcomingHoliday() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "april fool's day", 4, 1, 2012);
+ validateDate(reference, "black friday", 11, 25, 2011);
+ validateDate(reference, "christmas", 12, 25, 2011);
+ validateDate(reference, "christmas eve", 12, 24, 2011);
+ validateDate(reference, "columbus day", 10, 8, 2012);
+ validateDate(reference, "earth day", 4, 22, 2012);
+ validateDate(reference, "easter", 4, 8, 2012);
+ validateDate(reference, "father's day", 6, 17, 2012);
+ validateDate(reference, "flag day", 6, 14, 2012);
+ validateDate(reference, "good friday", 4, 6, 2012);
+ validateDate(reference, "groundhog day", 2, 2, 2012);
+ validateDate(reference, "halloween", 10, 31, 2012);
+ validateDate(reference, "independence day", 7, 4, 2012);
+ validateDate(reference, "kwanzaa", 12, 26, 2011);
+ validateDate(reference, "labor day", 9, 3, 2012);
+ validateDate(reference, "mlk day", 1, 16, 2012);
+ validateDate(reference, "memorial day", 5, 28, 2012);
+ validateDate(reference, "mother's day", 5, 13, 2012);
+ validateDate(reference, "new year's day", 1, 1, 2012);
+ validateDate(reference, "new year's eve", 12, 31, 2011);
+ validateDate(reference, "patriot day", 9, 11, 2012);
+ validateDate(reference, "president's day", 2, 20, 2012);
+ validateDate(reference, "st patty's day", 3, 17, 2012);
+ validateDate(reference, "tax day", 4, 15, 2012);
+ validateDate(reference, "thanksgiving", 11, 24, 2011);
+ validateDate(reference, "election day", 11, 8, 2011);
+ validateDate(reference, "valentine day", 2, 14, 2012);
+ validateDate(reference, "veterans day", 11, 11, 2011);
+ }
+
+ @Test
+ void testRelativeHolidays() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "2 black fridays from now", 11, 23, 2012);
+ validateDate(reference, "three memorial days ago", 5, 25, 2009);
+ }
+
+ @Test
+ void testSeasonsByYear() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "spring 2010", 3, 20, 2010);
+ validateDate(reference, "spring 2018", 3, 20, 2018);
+ validateDate(reference, "spring 1928", 3, 20, 1928);
+
+ validateDate(reference, "summer 2012", 6, 20, 2012);
+ validateDate(reference, "summer 2015", 6, 21, 2015);
+ validateDate(reference, "summer 1960", 6, 21, 1960);
+
+ validateDate(reference, "fall 2011", 9, 23, 2011);
+ validateDate(reference, "fall 2012", 9, 22, 2012);
+ validateDate(reference, "autumn 2016", 9, 22, 2016);
+ validateDate(reference, "autumn 1800", 9, 23, 1800);
+
+ validateDate(reference, "winter 2016", 12, 21, 2016);
+ validateDate(reference, "winter 2011", 12, 22, 2011);
+ validateDate(reference, "winter 1900", 12, 22, 1900);
+ }
+
+ @Test
+ void testHolidaysByYear() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "april fool's day 2000", 4, 1, 2000);
+ validateDate(reference, "black friday 2001", 11, 23, 2001);
+ validateDate(reference, "christmas 2002", 12, 25, 2002);
+ validateDate(reference, "christmas eve 2003", 12, 24, 2003);
+ validateDate(reference, "columbus day 2010", 10, 11, 2010);
+ validateDate(reference, "earth day 2005", 4, 22, 2005);
+ validateDate(reference, "easter '06", 4, 16, 2006);
+ validateDate(reference, "father's day '07", 6, 17, 2007);
+ validateDate(reference, "flag day '08", 6, 14, 2008);
+ validateDate(reference, "good friday '09", 4, 10, 2009);
+ validateDate(reference, "groundhog day '10", 2, 2, 2010);
+ validateDate(reference, "halloween '11", 10, 31, 2011);
+ validateDate(reference, "independence day '12", 7, 4, 2012);
+ validateDate(reference, "kwanzaa '13", 12, 26, 2013);
+ validateDate(reference, "labor day '14", 9, 1, 2014);
+ validateDate(reference, "mlk day '15", 1, 19, 2015);
+ validateDate(reference, "memorial day '16", 5, 30, 2016);
+ validateDate(reference, "mother's day 2017", 5, 14, 2017);
+ validateDate(reference, "new year's day 2018", 1, 1, 2018);
+ validateDate(reference, "new year's eve 2019", 12, 31, 2018);
+ validateDate(reference, "patriot day 2020", 9, 11, 2020);
+ validateDate(reference, "president's day 2019", 2, 18, 2019);
+ validateDate(reference, "st patty's day 2018", 3, 17, 2018);
+ validateDate(reference, "tax day 2017", 4, 15, 2017);
+ validateDate(reference, "thanksgiving 2016", 11, 24, 2016);
+ validateDate(reference, "election day 2015", 11, 3, 2015);
+ validateDate(reference, "valentine day 2014", 2, 14, 2014);
+ validateDate(reference, "veterans day 2013", 11, 11, 2013);
+ }
+
+ @Test
+ void testHolidaysWithModifiers() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "four days before veterans day 2013", 11, 7, 2013);
+ validateDate(reference, "two days after two thanksgivings from now", 11, 24, 2012);
+ }
+
+ @Test
+ void testSeasonsWithModifiers() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("11/05/2011");
+ calendarSource = new CalendarSource(reference);
+
+ validateDate(reference, "four days before fall 2013", 9, 18, 2013);
+ validateDate(reference, "two days after two summers from now", 6, 23, 2013);
+ validateDate(reference, "three summers ago", 6, 21, 2009);
+ }
+}
diff --git a/src/test/java/org/natty/RecurrenceTest.java b/src/test/java/org/natty/RecurrenceTest.java
new file mode 100644
index 00000000..ddc65349
--- /dev/null
+++ b/src/test/java/org/natty/RecurrenceTest.java
@@ -0,0 +1,46 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Joe Stelmach
+ */
+class RecurrenceTest extends AbstractTest {
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ @Test
+ void testRelative() throws Exception {
+
+ final LocalDateTime refDateTime = LocalDateTime.of(2011, 3, 3, 12, 00, 00);
+ Date reference = Timestamp.valueOf(refDateTime);
+ calendarSource = new CalendarSource(reference);
+
+ DateGroup group = parser.parse("every friday until two tuesdays from now", reference).get(0);
+ assertThat(group.getDates()).hasSize(1);
+ validateDate(group.getDates().get(0), 3, 4, 2011);
+ assertThat(group.isRecurring()).isTrue();
+ validateDate(group.getRecursUntil(), 3, 15, 2011);
+
+ group = parser.parse("every saturday or sunday", reference).get(0);
+ assertThat(group.getDates()).hasSize(2);
+
+ validateDate(group.getDates().get(0), 3, 5, 2011);
+ validateDate(group.getDates().get(1), 3, 6, 2011);
+ assertThat(group.isRecurring()).isTrue();
+ assertThat(group.getRecursUntil()).isNull();
+ }
+}
diff --git a/src/test/java/org/natty/SearchTest.java b/src/test/java/org/natty/SearchTest.java
new file mode 100644
index 00000000..84e62e6d
--- /dev/null
+++ b/src/test/java/org/natty/SearchTest.java
@@ -0,0 +1,406 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * @author Joe Stelmach
+ */
+class SearchTest extends AbstractTest {
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ @Test
+ void test() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/20/2011");
+ calendarSource = new CalendarSource(reference);
+
+ Parser parser = new Parser();
+ List groups = parser.parse("golf tomorrow at 9 AM at pebble beach", reference);
+ assertThat(groups).hasSize(1);
+ DateGroup group = groups.get(0);
+ assertThat(group.getLine()).isEqualTo(1);
+ assertThat(group.getPosition()).isEqualTo(6);
+ assertThat(group.getDates()).hasSize(1);
+ validateDate(group.getDates().get(0), 2, 21, 2011);
+ validateTime(group.getDates().get(0), 9, 0, 0);
+
+ groups = parser.parse("golf with friends tomorrow at 10 ", reference);
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ assertThat(group.getLine()).isEqualTo(1);
+ assertThat(group.getPosition()).isEqualTo(19);
+ assertThat(group.getDates().size()).isEqualTo(1);
+ validateDate(group.getDates().get(0), 2, 21, 2011);
+ validateTime(group.getDates().get(0), 10, 0, 0);
+
+ parser = new Parser();
+ groups = parser.parse("golf with freinds tomorrow at 9 or Thursday at 10 am", reference);
+ assertThat(groups).hasSize(1);
+ List dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 21, 2011);
+ validateTime(dates.get(0), 9, 0, 0);
+ validateDate(dates.get(1), 2, 24, 2011);
+ validateTime(dates.get(1), 10, 0, 0);
+
+ groups = parser.parse("golf with friends tomorrow at 9 or Thursday at 10", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 21, 2011);
+ validateTime(dates.get(0), 9, 0, 0);
+ validateDate(dates.get(1), 2, 24, 2011);
+ validateTime(dates.get(1), 10, 0, 0);
+
+ groups = parser.parse("I want to go to park tomorrow and then email john@aol.com", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 21, 2011);
+
+ groups = parser.parse("I want to pay off all my debt in the next two years.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 20, 2011);
+ validateDate(dates.get(1), 2, 20, 2013);
+
+ groups = parser.parse("I want to purchase a car in the next month.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 3, 20, 2011);
+
+ groups = parser.parse("I want to plan a get-together with my friends for this Friday.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 25, 2011);
+
+ groups = parser.parse("I want to lose five pounds in the next two months.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 20, 2011);
+ validateDate(dates.get(1), 4, 20, 2011);
+
+ groups = parser.parse("I want to finalize my college schedule by next week.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 27, 2011);
+
+ groups = parser.parse("I want to read this weekend.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 26, 2011);
+
+ groups = parser.parse("I want to travel a big chunk of world next year.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 20, 2012);
+
+ groups = parser.parse("last 2 weeks", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 20, 2011);
+ validateDate(dates.get(1), 2, 6, 2011);
+
+ groups = parser.parse("last 5 years", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 20, 2011);
+ validateDate(dates.get(1), 2, 20, 2006);
+
+ groups = parser.parse("next 5 years", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(2);
+ validateDate(dates.get(0), 2, 20, 2011);
+ validateDate(dates.get(1), 2, 20, 2016);
+
+ groups = parser.parse("I want to go to my doctors appointment on May 15, 2011.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 5, 15, 2011);
+
+ groups = parser.parse("I intend to become a zombie on December, 21st 2012.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 12, 21, 2012);
+
+ groups = parser.parse("I want to hire a virtual assistant to do research for me on March 15, 2011", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 3, 15, 2011);
+
+ groups = parser.parse("I want to see my mother on sunday.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 27, 2011);
+
+ groups = parser.parse("I want to be able to jog 3 miles non-stop by September.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 1, 2011);
+
+ groups = parser.parse("I want to lose 10 lbs in 10 days", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 3, 2, 2011);
+
+ groups = parser.parse("I want to visit my grandfathers grave on December 30 2011", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 12, 30, 2011);
+
+ groups = parser.parse("i want to have 1 kid this year", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 20, 2011);
+
+ groups = parser.parse("save $1000 by September", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 1, 2011);
+
+ groups = parser.parse("have my son play at muse music in provo UT at the 3 band cause they always have fog on the third band at 7:30", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDateTime(dates.get(0), 2, 20, 2011, 7, 30, 0);
+
+ groups = parser.parse("i want to eat chinese tonight", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDateTime(dates.get(0), 2, 20, 2011, 20, 0, 0);
+
+ groups = parser.parse("Watch School Spirits on June 20 on syfy channel", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 6, 20, 2011);
+
+ groups = parser.parse("Watch School Spirits on June 20 on", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 6, 20, 2011);
+
+ groups = parser.parse("Watch School Spirits on June 20", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 6, 20, 2011);
+
+ groups = parser.parse("hillary clinton sep 13, 2013", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 13, 2013);
+ assertThat(groups.get(0).getPosition()).isEqualTo(17);
+ assertThat(groups.get(0).getText()).isEqualTo("sep 13, 2013");
+
+ groups = parser.parse("hillary clinton 9/13/2013", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 13, 2013);
+ assertThat(groups.get(0).getPosition()).isEqualTo(17);
+ assertThat(groups.get(0).getText()).isEqualTo("9/13/2013");
+
+ groups = parser.parse("hillary clintoo sep 13, 2013", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 13, 2013);
+ assertThat(groups.get(0).getPosition()).isEqualTo(17);
+ assertThat(groups.get(0).getText()).isEqualTo("sep 13, 2013");
+
+ groups = parser.parse("clinton sep 13 2013", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 13, 2013);
+ assertThat(groups.get(0).getPosition()).isEqualTo(9);
+ assertThat(groups.get(0).getText()).isEqualTo("sep 13 2013");
+
+ groups = parser.parse("wedding dinner with Pam", reference);
+ assertThat(groups.size()).isEqualTo(0);
+
+ groups = parser.parse("yummy fried chicken", reference);
+ assertThat(groups.size()).isEqualTo(0);
+
+ groups = parser.parse("I am friend with Pam", reference);
+ assertThat(groups.size()).isEqualTo(0);
+
+ groups = parser.parse("bfriday blah blah", reference);
+ assertThat(groups.size()).isEqualTo(0);
+
+ groups = parser.parse("dinner bmong friends", reference);
+ assertThat(groups.size()).isEqualTo(0);
+
+ groups = parser.parse("I know we should meet tomorrow", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 2, 21, 2011);
+
+ groups = parser.parse("**SHOT 01/31/15**", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 1, 31, 2015);
+
+ groups = parser.parse("KOSTROMA REGION, RUSSIA. SEPTEMBER 24, 2014. A woman cleaning up fallen leaves on the grounds of the Shchelykovo museum reserve of Russian playwright Alexander Ostrovsky.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 24, 2014);
+
+ groups = parser.parse("21 November 2014-NYC-USA **** STRICTLY NOT AVAILABLE FOR USA ***", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 11, 21, 2014);
+
+ groups = parser.parse("...all the backstory I needed in the first two minutes. From there, I....", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDateTime(dates.get(0), 2, 20, 2011, 0, 2, 0);
+
+ groups = parser.parse("earthquake occured 5km NNW of Vincent, California at 07:34 UTC! #earthquake #Vincent http://t.co/6e4fAC6hTU", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDateTime(dates.get(0), 2, 20, 2011, 2, 34, 0);
+
+ groups = parser.parse("Caricature: Person with anti-German foreign press. From: Le Rire, Paris, Spring 1933.", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 3, 20, 1933);
+
+ groups = parser.parse("Person with Generaloberst von Seeckt in Bad Nauheim. Photograph. Autumn 1936", reference);
+ assertThat(groups).hasSize(1);
+ dates = groups.get(0).getDates();
+ assertThat(dates).hasSize(1);
+ validateDate(dates.get(0), 9, 23, 1936);
+ }
+
+ @Test
+ public void testLocations() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/20/2011");
+ calendarSource = new CalendarSource(reference);
+
+ Parser parser = new Parser();
+ List groups = parser.parse("I want to go to the movies on september 1st. Or maybe we should go on October 3rd.", reference);
+ assertThat(groups.size()).isEqualTo(2);
+ DateGroup group = groups.get(0);
+ assertThat(group.getLine()).isEqualTo(1);
+ assertThat(group.getPosition()).isEqualTo(31);
+ group = groups.get(1);
+ assertThat(group.getLine()).isEqualTo(1);
+ assertThat(group.getPosition()).isEqualTo(72);
+
+ groups = parser.parse("I want to go to \nthe movies on september 1st to see The Alan Turing Movie.", reference);
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ assertThat(group.getLine()).isEqualTo(2);
+ assertThat(group.getPosition()).isEqualTo(15);
+ }
+
+ @Test
+ public void testPrefixSuffix() throws Exception {
+
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("2/20/2011");
+ calendarSource = new CalendarSource(reference);
+
+ // no prefix or suffix
+ Parser parser = new Parser();
+ List groups = parser.parse("Sept. 1st");
+ assertThat(groups).hasSize(1);
+ DateGroup group = groups.get(0);
+ assertThat(group.getPrefix(3)).hasSize(0);
+ assertThat(group.getSuffix(3)).hasSize(0);
+
+ // no prefix
+ groups = parser.parse("Sept. 1st is the date");
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ assertThat(group.getPrefix(3)).hasSize(0);
+ String suffix = group.getSuffix(3);
+ assertThat(suffix).isEqualTo(" is");
+
+ // no suffix
+ groups = parser.parse("The date is Sept. 1st");
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ String prefix = group.getPrefix(3);
+ assertThat(prefix).hasSize(3).isEqualTo("is ");
+ assertThat(group.getSuffix(3)).hasSize(0);
+
+ // ask for a larger prefix than available
+ groups = parser.parse("a Sept. 1st");
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ prefix = group.getPrefix(5);
+ assertThat(prefix).isEqualTo("a ");
+ assertThat(group.getSuffix(3)).hasSize(0);
+
+ // ask for a larger suffix than available
+ groups = parser.parse("Sept. 1st a");
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ suffix = group.getSuffix(5);
+ assertThat(suffix).isEqualTo(" a");
+ assertThat(group.getPrefix(3)).hasSize(0);
+
+ // ask for a larger prefix and suffix than available
+ groups = parser.parse("a Sept. 1st a");
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ prefix = group.getPrefix(5);
+ suffix = group.getSuffix(5);
+ assertThat(prefix).isEqualTo("a ");
+ assertThat(suffix).isEqualTo(" a");
+ }
+
+ @Test
+ public void testNoDates() {
+ List dates = parseCollection(new Date(), "Fried Chicken, Wedding Dinner");
+ assertThat(dates).hasSize(0);
+
+ parseCollection(new Date(), "Cleveland");
+ assertThat(dates).hasSize(0);
+ }
+
+}
diff --git a/src/test/java/org/natty/ThreadSafetyTest.java b/src/test/java/org/natty/ThreadSafetyTest.java
new file mode 100644
index 00000000..2209094c
--- /dev/null
+++ b/src/test/java/org/natty/ThreadSafetyTest.java
@@ -0,0 +1,76 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.sql.Timestamp;
+import java.text.DateFormat;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+import java.util.concurrent.atomic.AtomicInteger;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+class ThreadSafetyTest extends AbstractTest {
+
+ private final static int NUM_OF_THREADS = 10;
+ private final static int JOIN_TIMEOUT = 2000; // 2 seconds
+ private static DateFormat dateFormat;
+
+ private final AtomicInteger numOfCorrectResults = new AtomicInteger();
+
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ dateFormat = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, Locale.US);
+ initCalendarAndParser();
+ }
+
+ @Test
+ void testManyThreads() throws Exception {
+ Thread[] threads = new Thread[NUM_OF_THREADS];
+ for (int i = 0; i < NUM_OF_THREADS; i++) {
+ threads[i] = new Thread(new Tester(i));
+ }
+ for (Thread thread : threads) {
+ thread.start();
+ }
+ for (Thread thread : threads) {
+ thread.join(JOIN_TIMEOUT);
+ }
+ assertThat(numOfCorrectResults.get()).isEqualTo(NUM_OF_THREADS);
+ }
+
+ private class Tester implements Runnable {
+
+ private final Date referenceDate;
+ private final int baseMinute;
+
+ public Tester(int baseMinute) throws Exception {
+ final LocalDateTime refDateTime = LocalDateTime.of(2011, 3, 3, 1, baseMinute, 0);
+ this.referenceDate = Timestamp.valueOf(refDateTime);
+ this.baseMinute = baseMinute;
+ }
+
+ public void run() {
+ try {
+ // Imitate some long running task.
+ Thread.sleep(100);
+ } catch (Exception e) {
+ }
+ String newDate = "4/4/2012";
+ Date parsed = parser.parse(newDate, referenceDate).get(0).getDates().get(0);
+ validateThread(parsed, baseMinute);
+ numOfCorrectResults.incrementAndGet();
+ }
+ }
+
+ // We need this method because validateDate and validateTime are not thread safe.
+ private synchronized void validateThread(Date date, int baseMinute) {
+ validateDate(date, 4, 4, 2012);
+ validateTime(date, 1, baseMinute, 0);
+ }
+}
diff --git a/src/test/java/org/natty/TimeTest.java b/src/test/java/org/natty/TimeTest.java
new file mode 100644
index 00000000..1a3fa1de
--- /dev/null
+++ b/src/test/java/org/natty/TimeTest.java
@@ -0,0 +1,160 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.text.DateFormat;
+import java.util.Date;
+import java.util.List;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * Runs the parser through the various time formats
+ *
+ * @author Joe Stelmach
+ */
+class TimeTest extends AbstractTest {
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ /**
+ * Runs the parser through the various time formats
+ */
+ @Test
+ void testFormal() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("1/02/2011");
+ calendarSource = new CalendarSource(reference);
+ validateTime(reference, "0600h", 6, 0, 0);
+ validateTime(reference, "06:00h", 6, 0, 0);
+ validateTime(reference, "06:00 hours", 6, 0, 0);
+ validateTime(reference, "0000", 0, 0, 0);
+ validateTime(reference, "0700h", 7, 0, 0);
+ validateTime(reference, "6pm", 18, 0, 0);
+ validateTime(reference, "5:30 a.m.", 5, 30, 0);
+ validateTime(reference, "5", 5, 0, 0);
+ validateTime(reference, "12:59", 12, 59, 0);
+ validateTime(reference, "23:59:28", 23, 59, 28);
+ validateTime(reference, "00:00", 0, 0, 0);
+ validateTime(reference, "10:00am", 10, 0, 0);
+ validateTime(reference, "10a", 10, 0, 0);
+ validateTime(reference, "10am", 10, 0, 0);
+ validateTime(reference, "10a_m", 10, 0, 0);
+ validateTime(reference, "10", 10, 0, 0);
+ validateTime(reference, "8p", 20, 0, 0);
+ validateTime(reference, "8pm", 20, 0, 0);
+ validateTime(reference, "8 pm", 20, 0, 0);
+ validateTime(reference, "8 p_m", 20, 0, 0);
+ }
+
+ @Test
+ void testRelaxed() throws Exception {
+ Date reference = DateFormat.getDateInstance(DateFormat.SHORT).parse("1/02/2011");
+ calendarSource = new CalendarSource(reference);
+ validateTime(reference, "noon", 12, 0, 0);
+ validateTime(reference, "at noon", 12, 0, 0);
+ validateTime(reference, "afternoon", 12, 0, 0);
+ validateTime(reference, "midnight", 0, 0, 0);
+ validateTime(reference, "mid-night", 0, 0, 0);
+ validateTime(reference, "6 in the morning", 6, 0, 0);
+ validateTime(reference, "4 in the afternoon", 16, 0, 0);
+ validateTime(reference, "evening", 19, 0, 0);
+ validateTime(reference, "10 hours before noon", 2, 0, 0);
+ validateTime(reference, "10 hours before midnight", 14, 0, 0);
+ validateTime(reference, "5 hours after noon", 17, 0, 0);
+ validateTime(reference, "5 hours after midnight", 5, 0, 0);
+ validateTime(reference, "tonight", 20, 0, 0);
+ }
+
+ @Test
+ void testRelative() throws Exception {
+ Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
+ calendarSource = new CalendarSource(reference);
+ validateTime(reference, "in 5 seconds", 12, 0, 5);
+ validateTime(reference, "in 5 minutes", 12, 5, 0);
+ validateTime(reference, "in 5 hours", 17, 0, 0);
+ validateTime(reference, "4 seconds from now", 12, 0, 4);
+ validateTime(reference, "4 minutes from now", 12, 4, 0);
+ validateTime(reference, "4 hours from now", 16, 0, 0);
+ validateTime(reference, "next minute", 12, 1, 0);
+ validateTime(reference, "last minute", 11, 59, 0);
+ validateTime(reference, "next second", 12, 0, 1);
+ validateTime(reference, "this second", 12, 0, 0);
+ validateTime(reference, "this minute", 12, 0, 0);
+ validateTime(reference, "this hour", 12, 0, 0);
+ }
+
+ @Test
+ public void testAlternatives() throws Exception {
+ Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
+ calendarSource = new CalendarSource(reference);
+
+ List dates = parseCollection(reference, "12 or 12:30");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 12, 0, 0);
+ validateTime(dates.get(1), 12, 30, 0);
+
+ dates = parseCollection(reference, "12pm or 12:30");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 12, 0, 0);
+ validateTime(dates.get(1), 12, 30, 0);
+
+ dates = parseCollection(reference, "noon or 12:30");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 12, 0, 0);
+ validateTime(dates.get(1), 12, 30, 0);
+
+ dates = parseCollection(reference, "12 or 12:30am");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 0, 0, 0);
+ validateTime(dates.get(1), 0, 30, 0);
+ }
+
+ @Test
+ void testRange() throws Exception {
+ Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
+ calendarSource = new CalendarSource(reference);
+
+ List dates = parseCollection(reference, "for six hours");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 12, 0, 0);
+ validateTime(dates.get(1), 18, 0, 0);
+
+ dates = parseCollection(reference, "for 12 minutes");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 12, 0, 0);
+ validateTime(dates.get(1), 12, 12, 0);
+
+ dates = parseCollection(reference, "for 10 seconds");
+ assertThat(dates).hasSize(2);
+ validateTime(dates.get(0), 12, 0, 0);
+ validateTime(dates.get(1), 12, 0, 10);
+ }
+
+ @Test
+ void testText() throws Exception {
+ Date reference = DateFormat.getTimeInstance(DateFormat.SHORT).parse("12:00 pm");
+
+ List groups = parser.parse("5.30pm", reference);
+ assertThat(groups).hasSize(1);
+ DateGroup group = groups.get(0);
+ assertThat(group.getDates()).hasSize(1);
+ validateTime(group.getDates().get(0), 17, 30, 0);
+ assertThat(group.getText()).isEqualTo("5.30pm");
+
+ groups = parser.parse("5:30pm", reference);
+ assertThat(groups).hasSize(1);
+ group = groups.get(0);
+ assertThat(group.getDates()).hasSize(1);
+
+ validateTime(group.getDates().get(0), 17, 30, 0);
+ assertThat(group.getText()).isEqualTo("5:30pm");
+
+ }
+}
diff --git a/src/test/java/org/natty/TimeZoneTest.java b/src/test/java/org/natty/TimeZoneTest.java
new file mode 100644
index 00000000..76d79342
--- /dev/null
+++ b/src/test/java/org/natty/TimeZoneTest.java
@@ -0,0 +1,42 @@
+package org.natty;
+
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
+
+import java.sql.Timestamp;
+import java.time.LocalDateTime;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+class TimeZoneTest extends AbstractTest {
+
+ @BeforeAll
+ public static void oneTime() {
+ Locale.setDefault(Locale.US);
+ TimeZone.setDefault(TimeZone.getTimeZone("US/Eastern"));
+ initCalendarAndParser();
+ }
+
+ @Test
+ void testSpecific() throws Exception {
+ final LocalDateTime refDateTime = LocalDateTime.of(2012, 5, 19, 12, 0, 0);
+ Date reference = Timestamp.valueOf(refDateTime);
+ calendarSource = new CalendarSource(reference);
+
+ validateDateTime(reference, "2011-06-17T07:00:00Z", 6, 17, 2011, 3, 0, 0);
+ validateDateTime(reference, "05-Aug-2013 14:10:56 UTC", 8, 5, 2013, 10, 10, 56);
+ validateDateTime(reference, "5/1/13 01:00:00-8", 5, 1, 2013, 5, 0, 0);
+ validateDateTime(reference, "5/1/13 01:00:00 UTC", 4, 30, 2013, 21, 0, 0);
+ validateDateTime(reference, "5/1/13 01:00:00 UTC+8", 4, 30, 2013, 13, 0, 0);
+ validateDateTime(reference, "5/1/13 01:00:00 GMT-1", 4, 30, 2013, 22, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 eastern time", 5, 20, 2012, 10, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 central time", 5, 20, 2012, 11, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 central", 5, 20, 2012, 11, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 mountain time", 5, 20, 2012, 12, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 pacific time", 5, 20, 2012, 13, 0, 0);
+ validateDateTime(reference, "tomorrow, 10pm pacific", 5, 21, 2012, 1, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 alaska time", 5, 20, 2012, 14, 0, 0);
+ validateDateTime(reference, "tomorrow, 10 hawaii time", 5, 20, 2012, 16, 0, 0);
+ }
+}
diff --git a/src/test/java/org/natty/grammar/AbstractGrammarTest.java b/src/test/java/org/natty/grammar/AbstractGrammarTest.java
new file mode 100644
index 00000000..b5867137
--- /dev/null
+++ b/src/test/java/org/natty/grammar/AbstractGrammarTest.java
@@ -0,0 +1,52 @@
+package org.natty.grammar;
+
+import org.antlr.runtime.ANTLRInputStream;
+import org.antlr.runtime.CommonTokenStream;
+import org.antlr.runtime.ParserRuleReturnScope;
+import org.antlr.runtime.tree.CommonTree;
+import org.antlr.runtime.tree.CommonTreeNodeStream;
+import org.antlr.runtime.tree.Tree;
+import org.natty.ANTLRNoCaseInputStream;
+import org.natty.ParseListener;
+import org.natty.generated.DateLexer;
+import org.natty.generated.DateParser;
+import org.natty.generated.TreeRewrite;
+
+import java.io.ByteArrayInputStream;
+import java.lang.reflect.Method;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public abstract class AbstractGrammarTest {
+ protected String ruleName;
+
+ protected void assertAST(String input, String ast) throws Exception {
+ assertThat(buildAST(input)).isEqualTo(ast);
+ }
+
+ protected String buildAST(String value) throws Exception {
+ DateParser parser = buildParser(value);
+ Class> klass = Class.forName("org.natty.generated.DateParser");
+ Method meth = klass.getMethod(ruleName, (Class>[]) null);
+ ParserRuleReturnScope ret = (ParserRuleReturnScope) meth.invoke(parser, (Object[]) null);
+
+ Tree tree = (Tree) ret.getTree();
+ // rewrite the tree (temporary fix for http://www.antlr.org/jira/browse/ANTLR-427)
+ CommonTreeNodeStream nodes = new CommonTreeNodeStream(tree);
+ TreeRewrite s = new TreeRewrite(nodes);
+ tree = (CommonTree) s.downup(tree);
+
+ return tree.toStringTree();
+ }
+
+ private DateParser buildParser(String value) throws Exception {
+ // lex
+ ANTLRInputStream input = new ANTLRNoCaseInputStream(new ByteArrayInputStream(value.getBytes()));
+ DateLexer lexer = new DateLexer(input);
+ CommonTokenStream tokens = new CommonTokenStream(lexer);
+
+ // parse
+ ParseListener listener = new ParseListener();
+ return new DateParser(tokens, listener);
+ }
+}
diff --git a/src/test/java/org/natty/grammar/DateGrammarTest.java b/src/test/java/org/natty/grammar/DateGrammarTest.java
new file mode 100644
index 00000000..bf5d44e1
--- /dev/null
+++ b/src/test/java/org/natty/grammar/DateGrammarTest.java
@@ -0,0 +1,639 @@
+package org.natty.grammar;
+
+
+import org.junit.jupiter.api.Test;
+
+class DateGrammarTest extends AbstractGrammarTest {
+ @Test
+ void date() throws Exception {
+ ruleName = "date";
+
+ assertAST("the day before yesterday", "(RELATIVE_DATE (SEEK < by_day 1 (RELATIVE_DATE (SEEK < by_day 1 day))))");
+ assertAST("1st oct in the year '89", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89))");
+ assertAST("2009-10-10", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10) (YEAR_OF 2009))");
+ assertAST("seven years ago", "(RELATIVE_DATE (SEEK < by_day 7 year))");
+ assertAST("next monday", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 2)))");
+ }
+
+ @Test
+ void alternative_day_of_month_list() throws Exception {
+ ruleName = "alternative_day_of_month_list";
+
+ assertAST("mon may 15 or 16",
+ "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
+
+ assertAST("mon may 15 to 16",
+ "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
+
+ assertAST("mon may 15 and 16",
+ "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
+
+ assertAST("mon may 15 through 16",
+ "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
+
+ assertAST("mon may 15 or 16",
+ "(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 15))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 16)))");
+
+ assertAST("first or last day of september",
+ "(DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))) (DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))))");
+
+ assertAST("first or last day of september at 5pm",
+ "(DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (EXPLICIT_SEEK (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm))");
+
+
+ assertAST("first or last day of next september at 6am",
+ "(DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am))");
+
+ assertAST("first or last day of 2 septembers from now at 5pm",
+ "(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 1))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK (DAY_OF_MONTH 31))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm))");
+ }
+
+ @Test
+ void global_date_prefix() throws Exception {
+ ruleName = "global_date_prefix";
+
+ assertAST("the day after", "> by_day 1");
+ assertAST("day after", "> by_day 1");
+ assertAST("2 days after", "> by_day 2");
+ assertAST("three days before", "< by_day 3");
+ assertAST("six months after", "> by_month 6");
+ assertAST("3 weeks before", "< by_week 3");
+ assertAST("10 years after", "> by_year 10");
+ assertAST("the day before", "< by_day 1");
+ assertAST("day before", "< by_day 1");
+ }
+
+ @Test
+ void relaxed_date() throws Exception {
+ ruleName = "relaxed_date";
+
+ assertAST("oct 1, 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
+ assertAST("oct. 1, 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
+ assertAST("oct 1,1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
+ assertAST("1st oct in the year '89", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89))");
+ assertAST("thirty first of december '80", "(EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 31) (YEAR_OF 80))");
+ assertAST("the first of december in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 1) (YEAR_OF 1980))");
+ assertAST("the 2 of february in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
+ assertAST("the 2nd of february in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
+ assertAST("the second of february in the year 1980", "(EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
+ assertAST("jan. 2nd", "(EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 2))");
+ assertAST("sun, nov 21 2010", "(EXPLICIT_DATE (MONTH_OF_YEAR 11) (DAY_OF_MONTH 21) (DAY_OF_WEEK 1) (YEAR_OF 2010))");
+ }
+
+ @Test
+ void formal_date() throws Exception {
+ ruleName = "formal_date";
+
+ assertAST("2009-10-10", "(EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10) (YEAR_OF 2009))");
+ assertAST("1980-1-2", "(EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 2) (YEAR_OF 1980))");
+ assertAST("12/12/12", "(EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 12) (YEAR_OF 12))");
+ assertAST("3/4", "(EXPLICIT_DATE (MONTH_OF_YEAR 3) (DAY_OF_MONTH 4))");
+ assertAST("sun, 11/21/2010", "(EXPLICIT_DATE (MONTH_OF_YEAR 11) (DAY_OF_MONTH 21) (DAY_OF_WEEK 1) (YEAR_OF 2010))");
+ }
+
+ @Test
+ void formal_month_of_year() throws Exception {
+ ruleName = "formal_month_of_year";
+
+ assertAST("01", "(MONTH_OF_YEAR 01)");
+ assertAST("1", "(MONTH_OF_YEAR 1)");
+ assertAST("02", "(MONTH_OF_YEAR 02)");
+ assertAST("2", "(MONTH_OF_YEAR 2)");
+ assertAST("03", "(MONTH_OF_YEAR 03)");
+ assertAST("3", "(MONTH_OF_YEAR 3)");
+ assertAST("04", "(MONTH_OF_YEAR 04)");
+ assertAST("4", "(MONTH_OF_YEAR 4)");
+ assertAST("05", "(MONTH_OF_YEAR 05)");
+ assertAST("5", "(MONTH_OF_YEAR 5)");
+ assertAST("06", "(MONTH_OF_YEAR 06)");
+ assertAST("6", "(MONTH_OF_YEAR 6)");
+ assertAST("07", "(MONTH_OF_YEAR 07)");
+ assertAST("7", "(MONTH_OF_YEAR 7)");
+ assertAST("08", "(MONTH_OF_YEAR 08)");
+ assertAST("8", "(MONTH_OF_YEAR 8)");
+ assertAST("09", "(MONTH_OF_YEAR 09)");
+ assertAST("9", "(MONTH_OF_YEAR 9)");
+ assertAST("10", "(MONTH_OF_YEAR 10)");
+ assertAST("11", "(MONTH_OF_YEAR 11)");
+ assertAST("12", "(MONTH_OF_YEAR 12)");
+ //"00" FAIL
+ //"0" FAIL
+ //"13" FAIL
+ }
+
+ @Test
+ void formal_day_of_month() throws Exception {
+ ruleName = "formal_day_of_month";
+
+ assertAST("01", "(DAY_OF_MONTH 01)");
+ assertAST("1", "(DAY_OF_MONTH 1)");
+ assertAST("02", "(DAY_OF_MONTH 02)");
+ assertAST("2", "(DAY_OF_MONTH 2)");
+ assertAST("03", "(DAY_OF_MONTH 03)");
+ assertAST("3", "(DAY_OF_MONTH 3)");
+ assertAST("04", "(DAY_OF_MONTH 04)");
+ assertAST("4", "(DAY_OF_MONTH 4)");
+ assertAST("05", "(DAY_OF_MONTH 05)");
+ assertAST("5", "(DAY_OF_MONTH 5)");
+ assertAST("06", "(DAY_OF_MONTH 06)");
+ assertAST("6", "(DAY_OF_MONTH 6)");
+ assertAST("07", "(DAY_OF_MONTH 07)");
+ assertAST("7", "(DAY_OF_MONTH 7)");
+ assertAST("08", "(DAY_OF_MONTH 08)");
+ assertAST("8", "(DAY_OF_MONTH 8)");
+ assertAST("09", "(DAY_OF_MONTH 09)");
+ assertAST("9", "(DAY_OF_MONTH 9)");
+ assertAST("10", "(DAY_OF_MONTH 10)");
+ assertAST("11", "(DAY_OF_MONTH 11)");
+ assertAST("12", "(DAY_OF_MONTH 12)");
+ assertAST("13", "(DAY_OF_MONTH 13)");
+ assertAST("14", "(DAY_OF_MONTH 14)");
+ assertAST("15", "(DAY_OF_MONTH 15)");
+ assertAST("16", "(DAY_OF_MONTH 16)");
+ assertAST("17", "(DAY_OF_MONTH 17)");
+ assertAST("18", "(DAY_OF_MONTH 18)");
+ assertAST("19", "(DAY_OF_MONTH 19)");
+ assertAST("20", "(DAY_OF_MONTH 20)");
+ assertAST("21", "(DAY_OF_MONTH 21)");
+ assertAST("22", "(DAY_OF_MONTH 22)");
+ assertAST("23", "(DAY_OF_MONTH 23)");
+ assertAST("24", "(DAY_OF_MONTH 24)");
+ assertAST("25", "(DAY_OF_MONTH 25)");
+ assertAST("26", "(DAY_OF_MONTH 26)");
+ assertAST("27", "(DAY_OF_MONTH 27)");
+ assertAST("28", "(DAY_OF_MONTH 28)");
+ assertAST("29", "(DAY_OF_MONTH 29)");
+ assertAST("30", "(DAY_OF_MONTH 30)");
+ assertAST("31", "(DAY_OF_MONTH 31)");
+ //"00" FAIL
+ //"0" FAIL
+ //"32" FAIL
+ }
+
+ @Test
+ void formal_year() throws Exception {
+ ruleName = "formal_year";
+
+ assertAST("1999", "(YEAR_OF 1999)");
+ assertAST("80", "(YEAR_OF 80)");
+ assertAST("0000", "(YEAR_OF 0000)");
+ assertAST("2010", "(YEAR_OF 2010)");
+ assertAST("03", "(YEAR_OF 03)");
+ //"037" FAIL
+ //"0" FAIL
+ //"03700" FAIL
+ }
+
+ @Test
+ void formal_year_four_digits() throws Exception {
+ ruleName = "formal_year_four_digits";
+
+ assertAST("1999", "(YEAR_OF 1999)");
+ assertAST("0000", "(YEAR_OF 0000)");
+ assertAST("2010", "(YEAR_OF 2010)");
+ //assertAST("80" FAIL
+ //assertAST("03" FAIL
+ //assertAST("037" FAIL
+ //assertAST("0" FAIL
+ //assertAST("03700" FAIL
+ }
+
+ @Test
+ void formal_date_separator() throws Exception {
+ ruleName = "formal_date_separator";
+
+ assertAST("-", "-");
+ assertAST("/", "/");
+ }
+
+ @Test
+ void relative_date() throws Exception {
+ ruleName = "relative_date";
+
+ assertAST("yesterday", "(RELATIVE_DATE (SEEK < by_day 1 day))");
+ assertAST("tomorrow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
+ assertAST("in 3 days", "(RELATIVE_DATE (SEEK > by_day 3 day))");
+ assertAST("3 days ago", "(RELATIVE_DATE (SEEK < by_day 3 day))");
+ assertAST("in 3 weeks", "(RELATIVE_DATE (SEEK > by_day 3 week))");
+ assertAST("four weeks ago", "(RELATIVE_DATE (SEEK < by_day 4 week))");
+ assertAST("in 3 months", "(RELATIVE_DATE (SEEK > by_day 3 month))");
+ assertAST("three months ago", "(RELATIVE_DATE (SEEK < by_day 3 month))");
+ assertAST("in 3 years", "(RELATIVE_DATE (SEEK > by_day 3 year))");
+ assertAST("seven years ago", "(RELATIVE_DATE (SEEK < by_day 7 year))");
+ assertAST("60 years ago", "(RELATIVE_DATE (SEEK < by_day 60 year))");
+ assertAST("32 days ago", "(RELATIVE_DATE (SEEK < by_day 32 day))");
+ assertAST("150 days ago", "(RELATIVE_DATE (SEEK < by_day 150 day))");
+ assertAST("1500 days ago", "(RELATIVE_DATE (SEEK < by_day 1500 day))");
+ assertAST("next monday", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 2)))");
+ assertAST("next mon", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 2)))");
+ assertAST("4 mondays from now", "(RELATIVE_DATE (SEEK > by_day 4 (DAY_OF_WEEK 2)))");
+ assertAST("4 mondays from today", "(RELATIVE_DATE (SEEK > by_day 4 (DAY_OF_WEEK 2)))");
+ assertAST("next weekend", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 7)))");
+ assertAST("six mondays ago", "(RELATIVE_DATE (SEEK < by_day 6 (DAY_OF_WEEK 2)))");
+ assertAST("last monday", "(RELATIVE_DATE (SEEK < by_week 1 (DAY_OF_WEEK 2)))");
+ assertAST("last mon", "(RELATIVE_DATE (SEEK < by_week 1 (DAY_OF_WEEK 2)))");
+ assertAST("this past mon", "(RELATIVE_DATE (SEEK < by_day 1 (DAY_OF_WEEK 2)))");
+ assertAST("this coming mon", "(RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 2)))");
+ assertAST("this upcoming mon", "(RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 2)))");
+ assertAST("next thurs", "(RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5)))");
+ assertAST("next month", "(RELATIVE_DATE (SEEK > by_week 1 month))");
+ assertAST("last month", "(RELATIVE_DATE (SEEK < by_week 1 month))");
+ assertAST("next week", "(RELATIVE_DATE (SEEK > by_week 1 week))");
+ assertAST("last week", "(RELATIVE_DATE (SEEK < by_week 1 week))");
+ assertAST("next year", "(RELATIVE_DATE (SEEK > by_week 1 year))");
+ assertAST("last year", "(RELATIVE_DATE (SEEK < by_week 1 year))");
+ assertAST("1 year 2 months ago", "(RELATIVE_DATE (SEEK < by_day 1 year) (SEEK < by_day 2 month))");
+ assertAST("1 year 2 months 3 days ago", "(RELATIVE_DATE (SEEK < by_day 1 year) (SEEK < by_day 2 month) (SEEK < by_day 3 day))");
+ assertAST("5 years 9 days after now", "(RELATIVE_DATE (SEEK > by_day 5 year) (SEEK > by_day 9 day))");
+ assertAST("5 years 3 months 9 days from now", "(RELATIVE_DATE (SEEK > by_day 5 year) (SEEK > by_day 3 month) (SEEK > by_day 9 day))");
+ }
+
+ @Test
+ void explicit_relative_date() throws Exception {
+ ruleName = "explicit_relative_date";
+
+ assertAST("monday of last week",
+ "(RELATIVE_DATE (SEEK < by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("tuesday of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 3)))");
+
+ assertAST("the monday of 2 weeks ago",
+ "(RELATIVE_DATE (SEEK < by_day 2 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("tuesday of 3 weeks from now",
+ "(RELATIVE_DATE (SEEK > by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 3)))");
+
+ assertAST("monday of 3 weeks from now",
+ "(RELATIVE_DATE (SEEK > by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("1st of three months ago",
+ "(RELATIVE_DATE (SEEK < by_day 3 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
+
+ assertAST("10th of next month",
+ "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 10)))");
+
+ assertAST("28th of last month",
+ "(RELATIVE_DATE (SEEK < by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 28)))");
+
+ assertAST("10th of next october",
+ "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 10)) (EXPLICIT_SEEK (DAY_OF_MONTH 10)))");
+
+ assertAST("the 30th of this month",
+ "(RELATIVE_DATE (SEEK > by_day 0 month) (EXPLICIT_SEEK (DAY_OF_MONTH 30)))");
+
+ assertAST("10th of the month after next",
+ "(RELATIVE_DATE (SEEK > by_day 2 month) (EXPLICIT_SEEK (DAY_OF_MONTH 10)))");
+
+ assertAST("the last thursday in november",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5)))");
+
+ assertAST("the last thursday in november 1999",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK (YEAR_OF 1999)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5)))");
+
+ assertAST("3rd wed in next month",
+ "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK 3 (DAY_OF_WEEK 4)))");
+
+ assertAST("the last sunday in november",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 1)))");
+
+ assertAST("the first wed. in january",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 1)) (EXPLICIT_SEEK 1 (DAY_OF_WEEK 4)))");
+
+ assertAST("the last day of february 1999",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 2)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)) (EXPLICIT_SEEK (YEAR_OF 1999)))");
+
+ assertAST("the first wed. in january in the year 2004",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 1)) (EXPLICIT_SEEK (YEAR_OF 2004)) (EXPLICIT_SEEK 1 (DAY_OF_WEEK 4)))");
+
+ assertAST("last monday of last month",
+ "(RELATIVE_DATE (SEEK < by_week 1 month) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 2)))");
+
+ assertAST("the last sunday of next nov",
+ "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 1)))");
+
+ assertAST("the 3rd sunday of 2 novembers from now",
+ "(RELATIVE_DATE (SEEK > by_day 2 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 3 (DAY_OF_WEEK 1)))");
+
+ assertAST("the last monday in 2 novembers ago",
+ "(RELATIVE_DATE (SEEK < by_day 2 (MONTH_OF_YEAR 11)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 2)))");
+
+ assertAST("the beginning of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("the end of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("the end of this week",
+ "(RELATIVE_DATE (SEEK > by_day 0 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("the start of this week",
+ "(RELATIVE_DATE (SEEK > by_day 0 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("start of 3 weeks from now",
+ "(RELATIVE_DATE (SEEK > by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("the end of 3 weeks ago",
+ "(RELATIVE_DATE (SEEK < by_day 3 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("the first day of this week",
+ "(RELATIVE_DATE (SEEK > by_day 0 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("the last day of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("first day of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 2)))");
+
+ assertAST("last day of last week",
+ "(RELATIVE_DATE (SEEK < by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("start of 3 months from now",
+ "(RELATIVE_DATE (SEEK > by_day 3 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
+
+ assertAST("beginning of next month",
+ "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
+
+ assertAST("end of next month",
+ "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
+
+ assertAST("last day of next month",
+ "(RELATIVE_DATE (SEEK > by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
+
+ assertAST("first day of 3 months from now",
+ "(RELATIVE_DATE (SEEK > by_day 3 month) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
+
+ assertAST("end of next october",
+ "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 10)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
+
+ assertAST("first day of feb",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 2)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
+
+ assertAST("last day of three februarys from now",
+ "(RELATIVE_DATE (SEEK > by_day 3 (MONTH_OF_YEAR 2)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
+
+ assertAST("in the end of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("at the end of last week",
+ "(RELATIVE_DATE (SEEK < by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("at the end of 2 weeks",
+ "(RELATIVE_DATE (SEEK > by_day 2 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("in the start of june",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 6)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))");
+
+ assertAST("at the end of next week",
+ "(RELATIVE_DATE (SEEK > by_week 1 week) (EXPLICIT_SEEK (DAY_OF_WEEK 6)))");
+
+ assertAST("at the end of last month",
+ "(RELATIVE_DATE (SEEK < by_week 1 month) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))");
+
+ assertAST("the second day of april",
+ "(RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 4)) (EXPLICIT_SEEK (DAY_OF_MONTH 2)))");
+
+ assertAST("the thirtieth day of next april",
+ "(RELATIVE_DATE (SEEK > by_week 1 (MONTH_OF_YEAR 4)) (EXPLICIT_SEEK (DAY_OF_MONTH 30)))");
+ }
+
+ @Test
+ void relative_occurrence_index() throws Exception {
+ ruleName = "relative_occurrence_index";
+
+ assertAST("1", "1");
+ assertAST("2", "2");
+ assertAST("3", "3");
+ assertAST("4", "4");
+ assertAST("5", "5");
+ assertAST("first", "1");
+ assertAST("second", "2");
+ assertAST("third", "3");
+ assertAST("fourth", "4");
+ assertAST("fifth", "5");
+ assertAST("last", "5");
+ //assertAST("sixth" FAIL);
+ //assertAST("6" FAIL);
+ }
+
+ @Test
+ void relative_target() throws Exception {
+ ruleName = "relative_target";
+
+ assertAST("sunday", "(DAY_OF_WEEK 1)");
+ assertAST("sundays", "(DAY_OF_WEEK 1)");
+ assertAST("sun", "(DAY_OF_WEEK 1)");
+ assertAST("monday", "(DAY_OF_WEEK 2)");
+ assertAST("mondays", "(DAY_OF_WEEK 2)");
+ assertAST("mon", "(DAY_OF_WEEK 2)");
+ assertAST("tuesday", "(DAY_OF_WEEK 3)");
+ assertAST("tuesdays", "(DAY_OF_WEEK 3)");
+ assertAST("tues", "(DAY_OF_WEEK 3)");
+ assertAST("tue", "(DAY_OF_WEEK 3)");
+ assertAST("wednesday", "(DAY_OF_WEEK 4)");
+ assertAST("wednesdays", "(DAY_OF_WEEK 4)");
+ assertAST("wed", "(DAY_OF_WEEK 4)");
+ assertAST("thursday", "(DAY_OF_WEEK 5)");
+ assertAST("thursdays", "(DAY_OF_WEEK 5)");
+ assertAST("thur", "(DAY_OF_WEEK 5)");
+ assertAST("thu", "(DAY_OF_WEEK 5)");
+ assertAST("friday", "(DAY_OF_WEEK 6)");
+ assertAST("fridays", "(DAY_OF_WEEK 6)");
+ assertAST("fri", "(DAY_OF_WEEK 6)");
+ assertAST("saturday", "(DAY_OF_WEEK 7)");
+ assertAST("saturdays", "(DAY_OF_WEEK 7)");
+ assertAST("sat", "(DAY_OF_WEEK 7)");
+ assertAST("day", "day");
+ assertAST("days", "day");
+ assertAST("week", "week");
+ assertAST("weeks", "week");
+ assertAST("month", "month");
+ assertAST("months", "month");
+ assertAST("year", "year");
+ assertAST("years", "year");
+ }
+
+ @Test
+ void relaxed_day_of_month() throws Exception {
+ ruleName = "relaxed_day_of_month";
+
+ assertAST("three", "(DAY_OF_MONTH 3)");
+ assertAST("third", "(DAY_OF_MONTH 3)");
+ assertAST("3rd", "(DAY_OF_MONTH 3)");
+ assertAST("3", "(DAY_OF_MONTH 3)");
+ assertAST("03", "(DAY_OF_MONTH 03)");
+ assertAST("21", "(DAY_OF_MONTH 21)");
+ assertAST("thirty one", "(DAY_OF_MONTH 31)");
+ assertAST("thirty-one", "(DAY_OF_MONTH 31)");
+ assertAST("thirty first", "(DAY_OF_MONTH 31)");
+ assertAST("thirty-first", "(DAY_OF_MONTH 31)");
+ assertAST("31st", "(DAY_OF_MONTH 31)");
+ //assertAST("32" FAIL
+ }
+
+ @Test
+ void relaxed_year() throws Exception {
+ ruleName = "relaxed_year";
+
+ assertAST("'69", "(YEAR_OF 69)");
+ assertAST("79", "(YEAR_OF 79)");
+ assertAST("2079", "(YEAR_OF 2079)");
+ assertAST("'80", "(YEAR_OF 80)");
+ assertAST("1979", "(YEAR_OF 1979)");
+ assertAST("2004", "(YEAR_OF 2004)");
+ assertAST("999", "(YEAR_OF 999)");
+ //assertAST("999" FAIL");
+ }
+
+ @Test
+ void relaxed_year_prefix() throws Exception {
+ ruleName = "relaxed_year_prefix";
+
+ //assertAST(", in the year ", ", in the year");
+ //assertAST(" in the year ", " in the year");
+ //assertAST("in the year ", "in the year");
+ //assertAST("in the yesr ", "in the year");
+ }
+
+ @Test
+ void implicit_prefix() throws Exception {
+ ruleName = "implicit_prefix";
+
+ assertAST("this", "> by_day 0");
+ }
+
+ @Test
+ void relative_date_prefix() throws Exception {
+ ruleName = "relative_date_prefix";
+
+ assertAST("this last", "< by_week 1");
+ assertAST("last", "< by_week 1");
+ assertAST("this past", "< by_day 1");
+ assertAST("past", "< by_day 1");
+ assertAST("this next", "> by_week 1");
+ assertAST("next", "> by_week 1");
+ assertAST("this coming", "> by_day 1");
+ assertAST("coming", "> by_day 1");
+ assertAST("this upcoming", "> by_day 1");
+ assertAST("upcoming", "> by_day 1");
+ assertAST("3", "> by_day 3");
+ assertAST("twenty-eight", "> by_day 28");
+ //assertAST("in 3" , "> by_day 3");
+ //assertAST("in twenty" , "> by_day 20");
+ }
+
+ @Test
+ void relative_date_suffix() throws Exception {
+ ruleName = "relative_date_suffix";
+
+ assertAST("from now", "> by_day");
+ assertAST("ago", "< by_day");
+ }
+
+ @Test
+ void relative_date_span() throws Exception {
+ ruleName = "relative_date_span";
+
+ assertAST("day", "day");
+ assertAST("days", "day");
+ assertAST("week", "week");
+ assertAST("weeks", "week");
+ assertAST("month", "month");
+ assertAST("months", "month");
+ assertAST("year", "year");
+ assertAST("years", "year");
+ }
+
+ @Test
+ void relaxed_month() throws Exception {
+ ruleName = "relaxed_month";
+
+ assertAST("january", "(MONTH_OF_YEAR 1)");
+ assertAST("jan", "(MONTH_OF_YEAR 1)");
+ assertAST("february", "(MONTH_OF_YEAR 2)");
+ assertAST("feb", "(MONTH_OF_YEAR 2)");
+ assertAST("march", "(MONTH_OF_YEAR 3)");
+ assertAST("mar", "(MONTH_OF_YEAR 3)");
+ assertAST("april", "(MONTH_OF_YEAR 4)");
+ assertAST("apr", "(MONTH_OF_YEAR 4)");
+ assertAST("may", "(MONTH_OF_YEAR 5)");
+ assertAST("june", "(MONTH_OF_YEAR 6)");
+ assertAST("jun", "(MONTH_OF_YEAR 6)");
+ assertAST("july", "(MONTH_OF_YEAR 7)");
+ assertAST("jul", "(MONTH_OF_YEAR 7)");
+ assertAST("august", "(MONTH_OF_YEAR 8)");
+ assertAST("aug", "(MONTH_OF_YEAR 8)");
+ assertAST("september", "(MONTH_OF_YEAR 9)");
+ assertAST("sep", "(MONTH_OF_YEAR 9)");
+ assertAST("sept", "(MONTH_OF_YEAR 9)");
+ assertAST("october", "(MONTH_OF_YEAR 10)");
+ assertAST("oct", "(MONTH_OF_YEAR 10)");
+ assertAST("november", "(MONTH_OF_YEAR 11)");
+ assertAST("nov", "(MONTH_OF_YEAR 11)");
+ assertAST("december", "(MONTH_OF_YEAR 12)");
+ assertAST("dec", "(MONTH_OF_YEAR 12)");
+ assertAST("jan.", "(MONTH_OF_YEAR 1)");
+ assertAST("feb.", "(MONTH_OF_YEAR 2)");
+ assertAST("mar.", "(MONTH_OF_YEAR 3)");
+ assertAST("apr.", "(MONTH_OF_YEAR 4)");
+ assertAST("jun.", "(MONTH_OF_YEAR 6)");
+ assertAST("jul.", "(MONTH_OF_YEAR 7)");
+ assertAST("aug.", "(MONTH_OF_YEAR 8)");
+ assertAST("sep.", "(MONTH_OF_YEAR 9)");
+ assertAST("sept.", "(MONTH_OF_YEAR 9)");
+ assertAST("oct.", "(MONTH_OF_YEAR 10)");
+ assertAST("nov.", "(MONTH_OF_YEAR 11)");
+ assertAST("dec.", "(MONTH_OF_YEAR 12)");
+ }
+
+ @Test
+ void day_of_week() throws Exception {
+ ruleName = "day_of_week";
+
+ assertAST("sunday", "(DAY_OF_WEEK 1)");
+ assertAST("sundays", "(DAY_OF_WEEK 1)");
+ assertAST("sun", "(DAY_OF_WEEK 1)");
+ assertAST("sun.", "(DAY_OF_WEEK 1)");
+ assertAST("monday", "(DAY_OF_WEEK 2)");
+ assertAST("mondays", "(DAY_OF_WEEK 2)");
+ assertAST("mon", "(DAY_OF_WEEK 2)");
+ assertAST("mon.", "(DAY_OF_WEEK 2)");
+ assertAST("tuesday", "(DAY_OF_WEEK 3)");
+ assertAST("tuesdays", "(DAY_OF_WEEK 3)");
+ assertAST("tues", "(DAY_OF_WEEK 3)");
+ assertAST("tues.", "(DAY_OF_WEEK 3)");
+ assertAST("tue", "(DAY_OF_WEEK 3)");
+ assertAST("tue.", "(DAY_OF_WEEK 3)");
+ assertAST("wednesday", "(DAY_OF_WEEK 4)");
+ assertAST("wednesdays", "(DAY_OF_WEEK 4)");
+ assertAST("wed", "(DAY_OF_WEEK 4)");
+ assertAST("wed.", "(DAY_OF_WEEK 4)");
+ assertAST("thursday", "(DAY_OF_WEEK 5)");
+ assertAST("thursdays", "(DAY_OF_WEEK 5)");
+ assertAST("thur", "(DAY_OF_WEEK 5)");
+ assertAST("thur.", "(DAY_OF_WEEK 5)");
+ assertAST("thu", "(DAY_OF_WEEK 5)");
+ assertAST("thu.", "(DAY_OF_WEEK 5)");
+ assertAST("friday", "(DAY_OF_WEEK 6)");
+ assertAST("fridays", "(DAY_OF_WEEK 6)");
+ assertAST("fri", "(DAY_OF_WEEK 6)");
+ assertAST("fri.", "(DAY_OF_WEEK 6)");
+ assertAST("saturday", "(DAY_OF_WEEK 7)");
+ assertAST("saturdays", "(DAY_OF_WEEK 7)");
+ assertAST("sat", "(DAY_OF_WEEK 7)");
+ assertAST("sat.", "(DAY_OF_WEEK 7)");
+ }
+
+ @Test
+ void named_relative_date() throws Exception {
+ ruleName = "named_relative_date";
+
+ assertAST("today", "(RELATIVE_DATE (SEEK > by_day 0 day))");
+ assertAST("now", "(RELATIVE_DATE (SEEK > by_day 0 day))");
+ assertAST("tomorow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
+ assertAST("tomorrow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
+ assertAST("tommorow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
+ assertAST("tommorrow", "(RELATIVE_DATE (SEEK > by_day 1 day))");
+ assertAST("yesterday", "(RELATIVE_DATE (SEEK < by_day 1 day))");
+ }
+}
diff --git a/src/test/java/org/natty/grammar/DateTimeGrammarTest.java b/src/test/java/org/natty/grammar/DateTimeGrammarTest.java
new file mode 100644
index 00000000..5a4f5c5e
--- /dev/null
+++ b/src/test/java/org/natty/grammar/DateTimeGrammarTest.java
@@ -0,0 +1,32 @@
+package org.natty.grammar;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+
+class DateTimeGrammarTest extends AbstractGrammarTest {
+
+ @ParameterizedTest(name = "{0}")
+ @CsvFileSource(
+ resources = "/test/datetime-alternative-test-data.csv",
+ delimiter = '|',
+ numLinesToSkip = 1,
+ useHeadersInDisplayName = false
+ )
+ void date_time_alternative(String input, String expectedAst) throws Exception {
+ ruleName = "date_time_alternative";
+ assertAST(input, expectedAst);
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @CsvFileSource(
+ resources = "/test/datetime-test-data.csv",
+ delimiter = '|',
+ numLinesToSkip = 1,
+ useHeadersInDisplayName = false
+ )
+ void date_time(String input, String expectedAst) throws Exception {
+ ruleName = "date_time";
+ assertAST(input, expectedAst);
+ }
+
+}
diff --git a/src/test/java/org/natty/grammar/HolidayGrammarTest.java b/src/test/java/org/natty/grammar/HolidayGrammarTest.java
new file mode 100644
index 00000000..15bfeb20
--- /dev/null
+++ b/src/test/java/org/natty/grammar/HolidayGrammarTest.java
@@ -0,0 +1,31 @@
+package org.natty.grammar;
+
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.CsvFileSource;
+
+public class HolidayGrammarTest extends AbstractGrammarTest {
+
+ @ParameterizedTest(name = "{0}")
+ @CsvFileSource(
+ resources = "/test/holidays-test-data.csv",
+ delimiter = '|',
+ numLinesToSkip = 1,
+ useHeadersInDisplayName = false
+ )
+ void names(String input, String expectedAst) throws Exception {
+ ruleName = "holiday_name";
+ assertAST(input, expectedAst);
+ }
+
+ @ParameterizedTest(name = "{0}")
+ @CsvFileSource(
+ resources = "/test/holiday-statement-test-data.csv",
+ delimiter = '|',
+ numLinesToSkip = 1,
+ useHeadersInDisplayName = false
+ )
+ void statments(String input, String expectedAst) throws Exception {
+ ruleName = "holiday";
+ assertAST(input, expectedAst);
+ }
+}
diff --git a/src/test/java/org/natty/grammar/NumericGrammarTest.java b/src/test/java/org/natty/grammar/NumericGrammarTest.java
new file mode 100644
index 00000000..3375cb0e
--- /dev/null
+++ b/src/test/java/org/natty/grammar/NumericGrammarTest.java
@@ -0,0 +1,412 @@
+package org.natty.grammar;
+
+
+import org.junit.jupiter.api.Test;
+
+class NumericGrammarTest extends AbstractGrammarTest {
+
+ @Test
+ void int_00_to_23_optional_prefix() throws Exception {
+ ruleName = "int_00_to_23_optional_prefix";
+ for (int i = 0; i <= 23; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ }
+
+ @Test
+ void test_int_00_to_59_mandatory_prefix() throws Exception {
+ ruleName = "int_00_to_59_mandatory_prefix";
+ for (int i = 0; i <= 59; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ /*
+ "0" FAIL
+ "1" FAIL
+ "2" FAIL
+ "3" FAIL
+ "4" FAIL
+ "5" FAIL
+ "6" FAIL
+ "7" FAIL
+ "8" FAIL
+ "9" FAIL
+ "60" FAIL
+ */
+ }
+
+ @Test
+ void test_int_00_to_99_mandatory_prefix() throws Exception {
+ ruleName = "int_00_to_99_mandatory_prefix";
+ for (int i = 0; i <= 99; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ /*
+ "0" FAIL
+ "1" FAIL
+ "2" FAIL
+ "3" FAIL
+ "4" FAIL
+ "5" FAIL
+ "6" FAIL
+ "7" FAIL
+ "8" FAIL
+ "9" FAIL
+ "100" FAIL
+ */
+ }
+
+ @Test
+ void int_1_to_9() throws Exception {
+ ruleName = "int_1_to_9";
+ for (int i = 1; i <= 9; i++) {
+ String value = String.format("%d", i);
+ assertAST(value, value);
+ }
+ /*
+ FAIL:
+ 0
+ 00
+ 01
+ 02
+ 03
+ 04
+ 05
+ 06
+ 07
+ 08
+ 09
+ */
+ }
+
+ @Test
+ void int_01_to_12() throws Exception {
+ ruleName = "int_01_to_12";
+ for (int i = 1; i < 13; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ /*
+ FAIL:
+ 0
+ 00
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ */
+ }
+
+
+ @Test
+ void int_13_to_23() throws Exception {
+ ruleName = "int_13_to_23";
+ for (int i = 13; i <= 23; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ }
+
+ @Test
+ void int_24_to_31() throws Exception {
+ ruleName = "int_24_to_31";
+ for (int i = 24; i <= 31; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ }
+
+ @Test
+ void int_32_to_59() throws Exception {
+ ruleName = "int_32_to_59";
+ for (int i = 32; i <= 59; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ }
+
+ @Test
+ void int_60_to_99() throws Exception {
+ ruleName = "int_60_to_99";
+ for (int i = 60; i <= 99; i++) {
+ String value = String.format("%02d", i);
+ assertAST(value, value);
+ }
+ }
+
+ @Test
+ void int_01_to_12_optional_prefix() throws Exception {
+ ruleName = "int_01_to_12_optional_prefix";
+ for (int i = 1; i <= 12; i++) {
+ String value = String.format("%d", i);
+ assertAST(value, value);
+
+ String valueWithPrefix = String.format("%02d", i);
+ assertAST(valueWithPrefix, valueWithPrefix);
+ }
+ }
+
+ @Test
+ void int_01_to_31_optional_prefix() throws Exception {
+ ruleName = "int_01_to_31_optional_prefix";
+ for (int i = 1; i <= 31; i++) {
+ String value = String.format("%d", i);
+ assertAST(value, value);
+
+ String valueWithPrefix = String.format("%02d", i);
+ assertAST(valueWithPrefix, valueWithPrefix);
+ }
+ }
+
+ @Test
+ void int_four_digits() throws Exception {
+ ruleName = "int_four_digits";
+
+ assertAST("0000", "0000");
+ assertAST("0100", "0100");
+ assertAST("0020", "0020");
+ assertAST("0003", "0003");
+ assertAST("9999", "9999");
+ assertAST("5050", "5050");
+ //"000" FAIL
+ //"33" FAIL
+ //"2" FAIL
+ }
+
+ @Test
+ void spelled_or_int_01_to_31_optional_prefix() throws Exception {
+ ruleName = "spelled_or_int_01_to_31_optional_prefix";
+
+ assertAST("one", "1");
+ assertAST("two", "2");
+ assertAST("three", "3");
+ assertAST("four", "4");
+ assertAST("five", "5");
+ assertAST("six", "6");
+ assertAST("seven", "7");
+ assertAST("eight", "8");
+ assertAST("nine", "9");
+ assertAST("ten", "10");
+ assertAST("eleven", "11");
+ assertAST("twelve", "12");
+ assertAST("thirteen", "13");
+ assertAST("fourteen", "14");
+ assertAST("fifteen", "15");
+ assertAST("sixteen", "16");
+ assertAST("seventeen", "17");
+ assertAST("eighteen", "18");
+ assertAST("nineteen", "19");
+ assertAST("twenty", "20");
+ assertAST("twenty one", "21");
+ assertAST("twenty-one", "21");
+ assertAST("twenty two", "22");
+ assertAST("twenty-two", "22");
+ assertAST("twenty three", "23");
+ assertAST("twenty-three", "23");
+ assertAST("twenty four", "24");
+ assertAST("twenty-four", "24");
+ assertAST("twenty five", "25");
+ assertAST("twenty-five", "25");
+ assertAST("twenty six", "26");
+ assertAST("twenty-six", "26");
+ assertAST("twenty seven", "27");
+ assertAST("twenty-seven", "27");
+ assertAST("twenty-eight", "28");
+ assertAST("twenty nine", "29");
+ assertAST("twenty-nine", "29");
+ assertAST("thirty", "30");
+ assertAST("thirty one", "31");
+ assertAST("thirty-one", "31");
+ assertAST("01", "01");
+ assertAST("1", "1");
+ assertAST("02", "02");
+ assertAST("2", "2");
+ assertAST("03", "03");
+ assertAST("3", "3");
+ assertAST("04", "04");
+ assertAST("4", "4");
+ assertAST("05", "05");
+ assertAST("5", "5");
+ assertAST("06", "06");
+ assertAST("6", "6");
+ assertAST("07", "07");
+ assertAST("7", "7");
+ assertAST("08", "08");
+ assertAST("8", "8");
+ assertAST("09", "09");
+ assertAST("9", "9");
+ assertAST("10", "10");
+ assertAST("11", "11");
+ assertAST("12", "12");
+ assertAST("13", "13");
+ assertAST("14", "14");
+ assertAST("15", "15");
+ assertAST("16", "16");
+ assertAST("17", "17");
+ assertAST("18", "18");
+ assertAST("19", "19");
+ assertAST("20", "20");
+ assertAST("21", "21");
+ assertAST("22", "22");
+ assertAST("23", "23");
+ assertAST("24", "24");
+ assertAST("25", "25");
+ assertAST("26", "26");
+ assertAST("27", "27");
+ assertAST("28", "28");
+ assertAST("29", "29");
+ assertAST("30", "30");
+ assertAST("31", "31");
+ //assertAST("zero", FAIL
+ }
+
+ @Test
+ void spelled_or_int_optional_prefix() throws Exception {
+ ruleName = "spelled_or_int_optional_prefix";
+
+ assertAST("1", "1");
+ assertAST("01", "01");
+ assertAST("60", "60");
+ assertAST("99", "99");
+ assertAST("one", "1");
+ assertAST("two", "2");
+ //"00" FAIL
+ //"0" FAIL
+ //"zero" FAIL
+ }
+
+ @Test
+ void spelled_one_to_thirty_one() throws Exception {
+ ruleName = "spelled_one_to_thirty_one";
+
+ assertAST("one", "1");
+ assertAST("two", "2");
+ assertAST("three", "3");
+ assertAST("four", "4");
+ assertAST("five", "5");
+ assertAST("six", "6");
+ assertAST("seven", "7");
+ assertAST("eight", "8");
+ assertAST("nine", "9");
+ assertAST("ten", "10");
+ assertAST("eleven", "11");
+ assertAST("twelve", "12");
+ assertAST("thirteen", "13");
+ assertAST("fourteen", "14");
+ assertAST("fifteen", "15");
+ assertAST("sixteen", "16");
+ assertAST("seventeen", "17");
+ assertAST("eighteen", "18");
+ assertAST("nineteen", "19");
+ assertAST("twenty", "20");
+ assertAST("twenty one", "21");
+ assertAST("twenty-one", "21");
+ assertAST("twenty two", "22");
+ assertAST("twenty-two", "22");
+ assertAST("twenty three", "23");
+ assertAST("twenty-three", "23");
+ assertAST("twenty four", "24");
+ assertAST("twenty-four", "24");
+ assertAST("twenty five", "25");
+ assertAST("twenty-five", "25");
+ assertAST("twenty six", "26");
+ assertAST("twenty-six", "26");
+ assertAST("twenty seven", "27");
+ assertAST("twenty-seven", "27");
+ assertAST("twenty-eight", "28");
+ assertAST("twenty nine", "29");
+ assertAST("twenty-nine", "29");
+ assertAST("thirty", "30");
+ assertAST("thirty one", "31");
+ assertAST("thirty-one", "31");
+
+ //"zero" FAIL
+ //"thirty two" FAIL
+ //"thirty-two" FAIL
+ }
+
+ @Test
+ void spelled_first_to_thirty_first() throws Exception {
+ ruleName = "spelled_first_to_thirty_first";
+
+ assertAST("first", "1");
+ assertAST("1st", "1");
+ assertAST("second", "2");
+ assertAST("2nd", "2");
+ assertAST("third", "3");
+ assertAST("3rd", "3");
+ assertAST("fourth", "4");
+ assertAST("4th", "4");
+ assertAST("fifth", "5");
+ assertAST("5th", "5");
+ assertAST("sixth", "6");
+ assertAST("6th", "6");
+ assertAST("seventh", "7");
+ assertAST("7th", "7");
+ assertAST("eighth", "8");
+ assertAST("8th", "8");
+ assertAST("ninth", "9");
+ assertAST("9th", "9");
+ assertAST("tenth", "10");
+ assertAST("10th", "10");
+ assertAST("eleventh", "11");
+ assertAST("11th", "11");
+ assertAST("twelfth", "12");
+ assertAST("12th", "12");
+ assertAST("thirteenth", "13");
+ assertAST("13th", "13");
+ assertAST("fourteenth", "14");
+ assertAST("14th", "14");
+ assertAST("fifteenth", "15");
+ assertAST("15th", "15");
+ assertAST("sixteenth", "16");
+ assertAST("16th", "16");
+ assertAST("seventeenth", "17");
+ assertAST("17th", "17");
+ assertAST("eighteenth", "18");
+ assertAST("18th", "18");
+ assertAST("nineteenth", "19");
+ assertAST("19th", "19");
+ assertAST("twentieth", "20");
+ assertAST("20th", "20");
+ assertAST("twenty-first", "21");
+ assertAST("twenty first", "21");
+ assertAST("21st", "21");
+ assertAST("twenty-second", "22");
+ assertAST("twenty second", "22");
+ assertAST("22nd", "22");
+ assertAST("twenty-third", "23");
+ assertAST("twenty third", "23");
+ assertAST("23rd", "23");
+ assertAST("twenty-fourth", "24");
+ assertAST("twenty fourth", "24");
+ assertAST("24th", "24");
+ assertAST("twenty-fifth", "25");
+ assertAST("twenty fifth", "25");
+ assertAST("25th", "25");
+ assertAST("twenty-sixth", "26");
+ assertAST("twenty sixth", "26");
+ assertAST("26th", "26");
+ assertAST("twenty-seventh", "27");
+ assertAST("twenty seventh", "27");
+ assertAST("27th", "27");
+ assertAST("twenty-eighth", "28");
+ assertAST("twenty eighth", "28");
+ assertAST("28th", "28");
+ assertAST("twenty-ninth", "29");
+ assertAST("twenty ninth", "29");
+ assertAST("29th", "29");
+ assertAST("thirtieth", "30");
+ assertAST("30th", "30");
+ assertAST("thirty-first", "31");
+ assertAST("thirty first", "31");
+ assertAST("31st", "31");
+ }
+}
diff --git a/src/test/java/org/natty/grammar/TimeGrammarTest.java b/src/test/java/org/natty/grammar/TimeGrammarTest.java
new file mode 100644
index 00000000..81e393a0
--- /dev/null
+++ b/src/test/java/org/natty/grammar/TimeGrammarTest.java
@@ -0,0 +1,114 @@
+package org.natty.grammar;
+
+
+import org.junit.jupiter.api.Test;
+
+class TimeGrammarTest extends AbstractGrammarTest {
+
+ @Test
+ void time_zone_abbreviation() throws Exception {
+ ruleName = "time_zone_abbreviation";
+
+ assertAST("est", "America/New_York");
+ assertAST("edt", "America/New_York");
+ assertAST("et", "America/New_York");
+ assertAST("pst", "America/Los_Angeles");
+ assertAST("pdt", "America/Los_Angeles");
+ assertAST("pt", "America/Los_Angeles");
+ assertAST("cst", "America/Chicago");
+ assertAST("cdt", "America/Chicago");
+ assertAST("ct", "America/Chicago");
+ assertAST("mst", "America/Denver");
+ assertAST("mdt", "America/Denver");
+ assertAST("mt", "America/Denver");
+ assertAST("akst", "America/Anchorage");
+ assertAST("akdt", "America/Anchorage");
+ assertAST("akt", "America/Anchorage");
+ assertAST("hast", "Pacific/Honolulu");
+ assertAST("hadt", "Pacific/Honolulu");
+ assertAST("hat", "Pacific/Honolulu");
+ assertAST("hst", "Pacific/Honolulu");
+ }
+
+ @Test
+ void meridian_indicator() throws Exception {
+ ruleName = "meridian_indicator";
+
+ assertAST("am", "am");
+ assertAST("a.m.", "am");
+ assertAST("a", "am");
+ assertAST("pm", "pm");
+ assertAST("p.m.", "pm");
+ assertAST("p", "pm");
+ }
+
+ @Test
+ void minutes() throws Exception {
+ ruleName = "minutes";
+ for (int i = 1; i <= 59; i++) {
+ String input = String.format("%02d", i);
+ assertAST(input, String.format("(MINUTES_OF_HOUR %02d)", i));
+ }
+
+ // TODO failures are not actually failing the parsing
+ assertAST("0", "(MINUTES_OF_HOUR ,1:0], resync=0>)");
+ //assertAST("1", "FAIL");
+ //assertAST("2", "FAIL");
+ //assertAST("3", "FAIL ");
+ //assertAST("4", "FAIL");
+ //assertAST("5", "FAIL");
+ //assertAST("6", "FAIL");
+ //assertAST("7", "FAIL");
+ //assertAST("8", "FAIL");
+ //assertAST("9", "FAIL");
+ //"60" FAIL
+ }
+
+ @Test
+ void hours() throws Exception {
+ ruleName = "hours";
+
+ // without prefix
+ for (int i = 1; i <= 23; i++) {
+ String input = String.format("%02d", i);
+ assertAST(input, String.format("(HOURS_OF_DAY %02d)", i));
+ }
+
+ // with prefix
+ for (int i = 1; i <= 23; i++) {
+ String input = String.format("%d", i);
+ assertAST(input, String.format("(HOURS_OF_DAY %d)", i));
+ }
+
+ //"-1" FAIL
+ //"24" FAIL
+ }
+
+ @Test
+ void explicit_time() throws Exception {
+ ruleName = "explicit_time";
+
+ assertAST("0600h", "(EXPLICIT_TIME (HOURS_OF_DAY 06) (MINUTES_OF_HOUR 00))");
+ assertAST("06:00h", "(EXPLICIT_TIME (HOURS_OF_DAY 06) (MINUTES_OF_HOUR 00))");
+ assertAST("06:00 hours", "(EXPLICIT_TIME (HOURS_OF_DAY 06) (MINUTES_OF_HOUR 00))");
+ assertAST("0000", "(EXPLICIT_TIME (HOURS_OF_DAY 00) (MINUTES_OF_HOUR 00))");
+ assertAST("0700h", "(EXPLICIT_TIME (HOURS_OF_DAY 07) (MINUTES_OF_HOUR 00))");
+ assertAST("6pm", "(EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)");
+ assertAST("5:30 a.m.", "(EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 30) am)");
+ assertAST("5", "(EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0))");
+ assertAST("12:59", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 59))");
+ assertAST("23:59", "(EXPLICIT_TIME (HOURS_OF_DAY 23) (MINUTES_OF_HOUR 59))");
+ assertAST("00:00", "(EXPLICIT_TIME (HOURS_OF_DAY 00) (MINUTES_OF_HOUR 00))");
+ assertAST("10:00am", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 00) am)");
+ assertAST("10a", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 0) am)");
+ assertAST("10am", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 0) am)");
+ assertAST("10", "(EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 0))");
+ assertAST("8p", "(EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) pm)");
+ assertAST("8pm", "(EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) pm)");
+ assertAST("8 pm", "(EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) pm)");
+ assertAST("noon", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)");
+ assertAST("afternoon", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)");
+ assertAST("midnight", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)");
+ assertAST("mid-night", "(EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)");
+ }
+}
diff --git a/src/test/resources/log4j.properties b/src/test/resources/log4j.properties
deleted file mode 100644
index 0506e387..00000000
--- a/src/test/resources/log4j.properties
+++ /dev/null
@@ -1,5 +0,0 @@
-log4j.rootLogger=error, stdout
-log4j.appender.stdout=org.apache.log4j.ConsoleAppender
-log4j.appender.stdout.Target=System.out
-log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
-log4j.appender.stdout.layout.ConversionPattern=%-5p %d{yyyy-MM-dd HH:mm:ss} %c{1}:%L - %m %n
\ No newline at end of file
diff --git a/src/test/resources/log4j2.xml b/src/test/resources/log4j2.xml
new file mode 100644
index 00000000..0c8e84ae
--- /dev/null
+++ b/src/test/resources/log4j2.xml
@@ -0,0 +1,14 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/logback-test.xml b/src/test/resources/logback-test.xml
new file mode 100644
index 00000000..6779d7da
--- /dev/null
+++ b/src/test/resources/logback-test.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
+
+
+ %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/test/resources/test/datetime-alternative-test-data.csv b/src/test/resources/test/datetime-alternative-test-data.csv
new file mode 100644
index 00000000..945fb6c9
--- /dev/null
+++ b/src/test/resources/test/datetime-alternative-test-data.csv
@@ -0,0 +1,21 @@
+input|expected_ast
+this wed. or next at 5pm|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)))
+feb 28th or 2 days after|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 28))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 28))))))
+january fourth or the friday after|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 4))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 6) (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 4))))))
+10/10/2008 or 10/12/2008|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10) (YEAR_OF 2008))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 12) (YEAR_OF 2008))))
+next wed or thursday|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5)))))
+next wed, thurs, fri|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 6)))))
+next wed, thurs, or fri at 6pm|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 5))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)) (DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 6))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) pm)))
+10/10 or 12/30 or 10/15 at 5pm|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 10))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 30))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 15)) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm)))
+monday to friday|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 6)))))
+1999-12-31 to tomorrow|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 31) (YEAR_OF 1999))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 day))))
+now to 2010-01-01|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 day))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 01) (DAY_OF_MONTH 01) (YEAR_OF 2010))))
+2009-03-10 9:00 to 11:00|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 03) (DAY_OF_MONTH 10) (YEAR_OF 2009)) (EXPLICIT_TIME (HOURS_OF_DAY 9) (MINUTES_OF_HOUR 00))) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 11) (MINUTES_OF_HOUR 00))))
+26 oct 10:00 am to 11:00 am|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 26)) (EXPLICIT_TIME (HOURS_OF_DAY 10) (MINUTES_OF_HOUR 00) am)) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 11) (MINUTES_OF_HOUR 00) am)))
+jan 1 to 2|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 1))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 2))))
+16:00 nov 6 to 17:00|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 11) (DAY_OF_MONTH 6)) (EXPLICIT_TIME (HOURS_OF_DAY 16) (MINUTES_OF_HOUR 00))) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 17) (MINUTES_OF_HOUR 00))))
+may 2nd to 5th|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 2))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 5) (DAY_OF_MONTH 5))))
+6am dec 5 to 7am|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 12) (DAY_OF_MONTH 5)) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am)) (DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 7) (MINUTES_OF_HOUR 0) am)))
+1/3 to 2/3|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 1) (DAY_OF_MONTH 3))) (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 3))))
+2/3 to in 1 week|(DATE_TIME_ALTERNATIVE (DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 2) (DAY_OF_MONTH 3))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 week))))
+first day of may to last day of may|(DATE_TIME_ALTERNATIVE (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 5)) (EXPLICIT_SEEK (DAY_OF_MONTH 1)))) (DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 5)) (EXPLICIT_SEEK (DAY_OF_MONTH 31)))))
diff --git a/src/test/resources/test/datetime-test-data.csv b/src/test/resources/test/datetime-test-data.csv
new file mode 100644
index 00000000..2ca44ac3
--- /dev/null
+++ b/src/test/resources/test/datetime-test-data.csv
@@ -0,0 +1,48 @@
+input|expected_ast
+seven years ago at 3pm|(DATE_TIME (RELATIVE_DATE (SEEK < by_day 7 year)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) pm))
+1st oct in the year '89 1300 hours|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))
+1st oct in the year '89 at 1300 hours|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))
+1st oct in the year '89, 13:00|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))
+1st oct in the year '89,13:00|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))
+1st oct in the year '89, at 13:00|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 89)) (EXPLICIT_TIME (HOURS_OF_DAY 13) (MINUTES_OF_HOUR 00)))
+3am on oct 1st 2010|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))
+3am, october first 2010|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))
+3am,october first 2010|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))
+3am, on october first 2010|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))
+3am october first 2010|(DATE_TIME (EXPLICIT_DATE (MONTH_OF_YEAR 10) (DAY_OF_MONTH 1) (YEAR_OF 2010)) (EXPLICIT_TIME (HOURS_OF_DAY 3) (MINUTES_OF_HOUR 0) am))
+next wed. at 5pm|(DATE_TIME (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))) (EXPLICIT_TIME (HOURS_OF_DAY 5) (MINUTES_OF_HOUR 0) pm))
+3 days after next wed|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 3 (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))))))
+the sunday after next wed|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 (DAY_OF_WEEK 1) (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))))))
+two days after today|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 day)))
+two days from today|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 day)))
+3 sundays after next wed|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 3 (DAY_OF_WEEK 1) (RELATIVE_DATE (SEEK > by_week 1 (DAY_OF_WEEK 4))))))
+the day after next|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 day)))
+the week after next|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 week)))
+the month after next|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 month)))
+the year after next|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 year)))
+wed of the week after next|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 week) (EXPLICIT_SEEK (DAY_OF_WEEK 4))))
+the 28th of the month after next|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 2 month) (EXPLICIT_SEEK (DAY_OF_MONTH 28))))
+6 in the morning|(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am))
+4 in the afternoon|(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 4) (MINUTES_OF_HOUR 0) pm))
+monday 6 in the morning|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2))) (EXPLICIT_TIME (HOURS_OF_DAY 6) (MINUTES_OF_HOUR 0) am))
+monday 4 in the afternoon|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2))) (EXPLICIT_TIME (HOURS_OF_DAY 4) (MINUTES_OF_HOUR 0) pm))
+monday 9 in the evening|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (DAY_OF_WEEK 2))) (EXPLICIT_TIME (HOURS_OF_DAY 9) (MINUTES_OF_HOUR 0) pm))
+this morning|(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 8) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am))
+this afternoon|(DATE_TIME (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm))
+final thursday in april|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 4)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5))))
+final thurs in sep|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 0 (MONTH_OF_YEAR 9)) (EXPLICIT_SEEK 5 (DAY_OF_WEEK 5))))
+tomorrow @ noon|(DATE_TIME (RELATIVE_DATE (SEEK > by_day 1 day)) (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm))
+6 hours ago|(DATE_TIME (RELATIVE_TIME (SEEK < by_day 6 hour)))
+10 hrs before noon|(DATE_TIME (RELATIVE_TIME (SEEK < by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)) 10 hour)))
+10 hr before midnight|(DATE_TIME (RELATIVE_TIME (SEEK < by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)) 10 hour)))
+5 hours after noon|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) pm)) 5 hour)))
+5 hours after midnight|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (EXPLICIT_SEEK (EXPLICIT_TIME (HOURS_OF_DAY 12) (MINUTES_OF_HOUR 0) (SECONDS_OF_MINUTE 0) am)) 5 hour)))
+in 5 seconds|(DATE_TIME (RELATIVE_TIME (SEEK > by_day 5 second)))
+in 5 minutes|(DATE_TIME (RELATIVE_TIME (SEEK > by_day 5 minute)))
+in 5 hours|(DATE_TIME (RELATIVE_TIME (SEEK > by_day 5 hour)))
+4 secs from now|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 second)))
+4 sec from now|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 second)))
+4 minutes from now|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 minute)))
+4 mins from now|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 minute)))
+4 min from now|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 minute)))
+4 hours from now|(DATE_TIME (RELATIVE_TIME (SEEK > by_day (RELATIVE_DATE (SEEK > by_day 0 day)) 4 hour)))
\ No newline at end of file
diff --git a/src/test/resources/test/holiday-statement-test-data.csv b/src/test/resources/test/holiday-statement-test-data.csv
new file mode 100644
index 00000000..042b9284
--- /dev/null
+++ b/src/test/resources/test/holiday-statement-test-data.csv
@@ -0,0 +1,14 @@
+input|expected_ast
+april fool's day|(SEEK > by_day 1 APRIL_FOOLS_DAY)
+next christmas|(SEEK > by_week 1 CHRISTMAS)
+coming christmas|(SEEK > by_day 1 CHRISTMAS)
+upcoming christmas|(SEEK > by_day 1 CHRISTMAS)
+last halloween|(SEEK < by_week 1 HALLOWEEN)
+past halloween|(SEEK < by_day 1 HALLOWEEN)
+in three christmases|(SEEK > by_day 3 CHRISTMAS)
+three christmases from now|(SEEK > by_day 3 CHRISTMAS)
+3 christmases ago|(SEEK < by_day 3 CHRISTMAS)
+2 april fool's days ago|(SEEK < by_day 2 APRIL_FOOLS_DAY)
+in 10 thanksgivings|(SEEK > by_day 10 THANKSGIVING)
+thanksgiving 2011|(EXPLICIT_SEEK THANKSGIVING (YEAR_OF 2011))
+christmas, '95|(EXPLICIT_SEEK CHRISTMAS (YEAR_OF 95))
\ No newline at end of file
diff --git a/src/test/resources/test/holidays-test-data.csv b/src/test/resources/test/holidays-test-data.csv
new file mode 100644
index 00000000..bd8b7c8a
--- /dev/null
+++ b/src/test/resources/test/holidays-test-data.csv
@@ -0,0 +1,68 @@
+input|expected_ast
+april fool's day|APRIL_FOOLS_DAY
+april fools day|APRIL_FOOLS_DAY
+april fool day|APRIL_FOOLS_DAY
+black friday|BLACK_FRIDAY
+black fri|BLACK_FRIDAY
+black fri.|BLACK_FRIDAY
+christmas|CHRISTMAS
+christmas day|CHRISTMAS
+christmas eve|CHRISTMAS_EVE
+christmas eve.|CHRISTMAS_EVE
+christmas evening|CHRISTMAS_EVE
+columbus day|COLUMBUS_DAY
+earth day|EARTH_DAY
+easter|EASTER
+easter day|EASTER
+easter sunday|EASTER
+father's day|FATHERS_DAY
+fathers day|FATHERS_DAY
+flag day|FLAG_DAY
+good friday|GOOD_FRIDAY
+good fri|GOOD_FRIDAY
+good fri.|GOOD_FRIDAY
+groundhog day|GROUNDHOG_DAY
+groundhogs day|GROUNDHOG_DAY
+groundhog's day|GROUNDHOG_DAY
+halloween|HALLOWEEN
+haloween|HALLOWEEN
+halloween day|HALLOWEEN
+independence day|INDEPENDENCE_DAY
+kwanzaa|KWANZAA
+kwanza|KWANZAA
+kwanzaa day|KWANZAA
+labor day|LABOR_DAY
+martin luther king day|MLK_DAY
+martin luther king jr.'s day|MLK_DAY
+martin luther king jr. day|MLK_DAY
+martin luther king jr day|MLK_DAY
+mlk day|MLK_DAY
+memorial day|MEMORIAL_DAY
+memorial day|MEMORIAL_DAY
+mothers day|MOTHERS_DAY
+mother's day|MOTHERS_DAY
+new year's day|NEW_YEARS_DAY
+new years day|NEW_YEARS_DAY
+new years|NEW_YEARS_DAY
+new year's eve|NEW_YEARS_EVE
+new years eve|NEW_YEARS_EVE
+new years eve.|NEW_YEARS_EVE
+patriot day|PATRIOT_DAY
+president's day|PRESIDENTS_DAY
+presidents day|PRESIDENTS_DAY
+president day|PRESIDENTS_DAY
+st. patricks day|ST_PATRICKS_DAY
+st patrick's day|ST_PATRICKS_DAY
+saint patrick's day|ST_PATRICKS_DAY
+saint paddy's day|ST_PATRICKS_DAY
+saint paddys day|ST_PATRICKS_DAY
+tax day|TAX_DAY
+thanksgiving|THANKSGIVING
+thanksgiving day|THANKSGIVING
+election day|ELECTION_DAY
+valentine's day|VALENTINES_DAY
+valentines day|VALENTINES_DAY
+valentine day|VALENTINES_DAY
+veterans day|VETERANS_DAY
+veteran's day|VETERANS_DAY
+veteran day|VETERANS_DAY
\ No newline at end of file