View Javadoc
1   /*
2    * Copyright (c) 2002-2025 Gargoyle Software Inc.
3    *
4    * Licensed under the Apache License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * https://www.apache.org/licenses/LICENSE-2.0
8    *
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed under the License is distributed on an "AS IS" BASIS,
11   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12   * See the License for the specific language governing permissions and
13   * limitations under the License.
14   */
15  package org.htmlunit.html;
16  
17  import java.time.LocalDateTime;
18  import java.time.format.DateTimeFormatter;
19  import java.time.format.DateTimeParseException;
20  import java.util.Map;
21  
22  import org.apache.commons.lang3.StringUtils;
23  import org.htmlunit.BrowserVersion;
24  import org.htmlunit.SgmlPage;
25  
26  /**
27   * Wrapper for the HTML element "input" where type is "datetime-local".
28   *
29   * @author Ahmed Ashour
30   * @author Frank Danek
31   * @author Anton Demydenko
32   */
33  public class HtmlDateTimeLocalInput extends HtmlInput implements LabelableElement {
34  
35      private static final DateTimeFormatter FORMATTER_ = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm");
36  
37      /**
38       * Creates an instance.
39       *
40       * @param qualifiedName the qualified name of the element type to instantiate
41       * @param page the page that contains this element
42       * @param attributes the initial attributes
43       */
44      HtmlDateTimeLocalInput(final String qualifiedName, final SgmlPage page,
45              final Map<String, DomAttr> attributes) {
46          super(qualifiedName, page, attributes);
47      }
48  
49      /**
50       * {@inheritDoc}
51       */
52      @Override
53      public void setDefaultChecked(final boolean defaultChecked) {
54          // Empty.
55      }
56  
57      /**
58       * {@inheritDoc}
59       */
60      @Override
61      public void setValue(final String newValue) {
62          try {
63              if (StringUtils.isNotEmpty(newValue)) {
64                  FORMATTER_.parse(newValue);
65              }
66              super.setValue(newValue);
67          }
68          catch (final DateTimeParseException ignored) {
69              // ignore
70          }
71      }
72  
73      /**
74       * {@inheritDoc}
75       */
76      @Override
77      public boolean isValid() {
78          return super.isValid() && isMaxValid() && isMinValid();
79      }
80  
81      /**
82       * Returns if the input element has a valid min value. Refer to the
83       * <a href="https://www.w3.org/TR/html5/sec-forms.html">HTML 5</a> documentation
84       * for details.
85       *
86       * @return if the input element has a valid min value
87       */
88      private boolean isMinValid() {
89          if (!getMin().isEmpty()) {
90              try {
91                  final LocalDateTime dateValue = LocalDateTime.parse(getRawValue(), FORMATTER_);
92                  final LocalDateTime minDate = LocalDateTime.parse(getMin(), FORMATTER_);
93                  return minDate.isEqual(dateValue) || minDate.isBefore(dateValue);
94              }
95              catch (final DateTimeParseException ignored) {
96                  // ignore
97              }
98          }
99          return true;
100     }
101 
102     /**
103      * Returns if the input element has a valid max value. Refer to the
104      * <a href="https://www.w3.org/TR/html5/sec-forms.html">HTML 5</a> documentation
105      * for details.
106      *
107      * @return if the input element has a valid max value
108      */
109     private boolean isMaxValid() {
110         if (!getMax().isEmpty()) {
111             try {
112                 final LocalDateTime dateValue = LocalDateTime.parse(getRawValue(), FORMATTER_);
113                 final LocalDateTime maxDate = LocalDateTime.parse(getMax(), FORMATTER_);
114                 return maxDate.isEqual(dateValue) || maxDate.isAfter(dateValue);
115             }
116             catch (final DateTimeParseException ignored) {
117                 // ignore
118             }
119         }
120         return true;
121     }
122 
123     @Override
124     protected void adjustValueAfterTypeChange(final HtmlInput oldInput, final BrowserVersion browserVersion) {
125         setValue("");
126     }
127 }