Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Having trouble making moment().utc() return a 2 digit month and year

I am trying to fix a bug that has appeared in a birthday component in my application. The component gets the date of birth from its props in this format 1997-08-16T00:00:00Z. The issue Im having is that when the DOB is set in the state it is being set as single digits for month and day instead of a two digit month and day. This is what the component looks like handling the DOB:

class DOB extends Component {
  constructor(props) {
    super(props);
    if (props.value) {
      const dv = moment(props.value).utc();
      this.state = {
        year: dv.year(),
        month: dv.month() + 1,
        day: dv.date()
      };
    } else {
      this.state = { year: "", month: "", day: "" };
    }
    this.onFieldChanged = this.onFieldChanged.bind(this);
  }

  onFieldChanged(field) {
    return event => {
      const newValue = event.target.value;
      if (!isDigits(newValue)) {
        return;
      }
      const nextField = {
        month: "day",
        day: "year"
      };
      const n = this.refs[nextField[field]];
      if (n && newValue.length === 2) {
        n.focus();
      }
      this.setState({ [field]: newValue });
      const { year, month, day } = { ...this.state, [field]: newValue };

      const dateString = `${year}-${month}-${day}`;
      if (year.length < 4 || month < 1 || day < 1) {
        return;
      }
      const date = new Date(Date.parse(dateString));
      const today = new Date();
      if (date instanceof Date && !isNaN(date.valueOf())) {
        if (
          date.getFullYear() > 1800 &&
          date.getFullYear() <= today.getFullYear() &&
          date.getDate() > 0 &&
          date.getDate() < 32 &&
          date.getMonth() >= 0 &&
          date.getMonth() < 12
        ) {
          this.props.onChange({ target: { value: dateString } });
        }
      }
    };
  }
return (
      <div className="dob-entry">
        <input
          type="tel"
          ref="month"
          placeholder="mm"
          maxLength="2"
          value={state.month}
          onChange={this.onFieldChanged("month")}
        />{" "}
        /
        <input
          type="tel"
          ref="day"
          placeholder="dd"
          maxLength="2"
          value={state.day}
          onChange={this.onFieldChanged("day")}
        />{" "}
        /
        <input
          className="number"
          type="tel"
          placeholder="yyyy"
          ref="year"
          maxLength="4"
          value={state.year}
          onChange={this.onFieldChanged("year")}
        />
      </div>
    );
}
export default DOB;

Im wondering if it is possible to have the state set to the full two digit values for day and month. In my code dv.year() and dv.month() are setting them to single digits. Ive tried setting the values using const dvf = moment(dv).format('DD/MM/YYYY') and using .splice() to take out the values I need for each field but it seems the backend is expecting the utc values not just a string of numbers. I havent used moment much so there is plenty I dont understand about it however it has to be possible to have it return the 2 digit values right? Any insight would be appreciated.

like image 691
CourtneyJ Avatar asked Jan 30 '26 05:01

CourtneyJ


1 Answers

There are a number of ways that you can fix this, and ultimately it's up to you to decide which way is best for your application.

I haven't used moment much myself either, but the problem is that dv.month() and dv.date() return numeric values, so something like '08' becomes 8. It appears that you want to want these values to be 2 digit strings, as there is no way to store 08 as a number, it'll always get changed to just 8.

If your code can handle these values being strings, you could simply adjust how the state is being set in the constructor. day: dv.date() can become something like day: dv.date() > 9 ? dv.date().toString() : '0' + dv.date() and then do similar with month.

Alternatively, you could use some string manipulation on the input date string to pull out the date and month as 2 digit strings. '1997-08-16T00:00:00Z'.slice(0, 10).split('-')[1] would return '08' and '1997-08-16T00:00:00Z'.slice(0, 10).split('-')[1] would return '16'.

These above methods mean that you'll be dealing with the date and month as strings, and you'll therefore have to make sure that any methods you plan to use on them later will work on strings.

The other option is to carry on storing the date and month as numbers, but then converting them to strings whenever you then go to send the value to the server.

I think this answers your question? Let me know if I'm missing anything.

like image 180
Ibz Avatar answered Feb 01 '26 19:02

Ibz