1

I have an HTML date input type and I'd like to manipulate it programatically in javascript. I'm just not getting it.

I see the most commonly accepted way of manipulating the date itself is like:

var c = new Date();
c.setDate(c.getDate() + 1);

I can get the date from the input:

c = document.getElementById("date1").valueAsDate

I can set the date of the input:

document.getElementById("date2").valueAsDate = c

I can manipulate the date in c:

c.setDate(c.getDate()+1)

Using c as an interim value, I can manipulate the value of one date object with respect to the other:

c = document.getElementById("date1").valueAsDate
c.setDate(c.getDate()+1)
document.getElementById("date2").valueAsDate = c

but no amount of manipulating the elements themselves am I able to transfer the date from one object to the other without using an interim variable.

For example, although:

c = document.getElementById("date1").valueAsDate

and

document.getElementById("date2").valueAsDate = c

are both valid, they are not directly manipulatable:

document.getElementById("date1").valueAsDate 
        = document.getElementById("date2").valueAsDate  

The above is INVALID

I seem to get close at times but I always need that interim variable.

I suppose I have 2 questions:

  1. What am I not understanding with these values that make them non transferable (between themselves)?

  2. What is the "cleanest" code to take the value from the document element, manipulate it by adding one day and sending it back

2
  • As far as I can tell, the HTML specification says you should be able to directly assign from one valueAsDate to another. Support for date inputs is not strong, and likely very few implementations fully support all the related functionality. You seem to already have "the cleanest code", just make it a function. Commented Aug 30, 2017 at 23:46
  • @RobG I would expect you could, but no amount of chopping and changing it around would get it to work. In the end I went with the three line approach, but if you could get it to work in one (unminified) line which is intuitive, I'd appreciate it... but I'm doing my best to best on ROFL Commented Aug 31, 2017 at 0:32

2 Answers 2

2

Copying the value using valueAsDate is within the HTML specification (latest editor's draft) and is possible in Chrome. However, Date inputs are not well supported yet so you should include feature testing to avoid errors and provide a fallback where features you want to use aren't supported.

"Clean" code is not necessarily the shortest or least code. I would aim for robustness, readability and maintainability over "clean".

To that end, there is no need to to use valueAsDate to copy the value from one input to another, just assign the value. That works everywhere.

// Copy using value from one input to another
// Supported everywhere
function copyValue() {
  document.getElementById('i1').value = document.getElementById('i0').value;
}

// Copy using valueAsDate from one input to another
// Throws errors where valueAsDate is not supported
function copyDate(){
  document.getElementById('i1').valueAsDate = document.getElementById('i0').valueAsDate;
}

// Copy using valueAsDate and add a day
// Include simple feature test, no fallback
function copyAddDate(){
  var d = document.getElementById('i0').valueAsDate;
  // If valueAsDate not supported, return
  if (d === null) {
    // Provide fallback
    console.log('valueAsDate not supported');
    return;
  }
  d.setDate(d.getDate() + 1);
  document.getElementById('i1').valueAsDate = d;
}
Date: <input type="date" id="i0" value="2017-08-20"><br>
Date: <input type="date" id="i1" readonly>
<button onclick="copyValue()">Copy value</button>
<button onclick="copyDate()">Copy date</button>
<button onclick="copyAddDate()">Copy and add 1 day</button>

However, input type date is not well supported (e.g. Safari, Firefox 49), so while this works in the latest Chrome browser, it doesn't in others.

So to answer your questions:

What am I not understanding with these values that make them non transferable (between themselves)?

Nothing, they should be in a compliant implementation. However, there aren't many of those.

What is the "cleanest" code to take the value from the document element, manipulate it by adding one day and sending it back

I think you already know that, but you should include some feature testing:

var c = document.getElementById("date1").valueAsDate;
// Check that a Date was returned
if (Object.prototype.toString.call(c) == '[object Date]') {
  c.setDate(c.getDate()+1);
  document.getElementById("date2").valueAsDate = c;
} else {
  console.log('Didn\'t get a Date');
}
Sign up to request clarification or add additional context in comments.

3 Comments

Note, the valueAsDate function follows the rules under "The algorithm to convert a string to a Date object" (and vice versa) in 4.10.5.1.7 - which specifically use UTC. Thus, setUTCDate/getUTCDate would be more appropriate. The difference would be noticed if the day crossed a DST transition.
awesome links! That's exactly the sort of thing I was looking for. Plus, I got fixated on valueAsDate that I forgot about the simple value. Regarding browsers, this project is not important, I'm writing something for personal use to manipulate some simple values on a local server (ie, it's only me using it in chrome). Thanks!
@MattJohnson—I understand where you're coming from, but testing for days going into and out of DST in various locations (including those where the change is at midnight) shows the same result whether UTC or local methods are used. I can conceive of how it may not work going out of DST where the day is 25 hours long, but it doesn't seem to matter in practice. Do you know of a case where it fails? I haven't worked through the DateFromTime(LocalTime(t)) algorithms longhand.
1
  1. I don't know the actual implementation, but I'm pretty sure valueAsDate returns a new Date that is a copy of the element's date and isn't a direct reference. valueAsDate is most likely just a getter/setter and not an actual property, meaning things like setDate won't mutate the underlying value as it's operating on a completely new, independent. So you need to retrieve the date, mutate it with setDate, then reassign the element's date to this newly mutated date.

  2. I would do exactly that. Write some kind of nice function like

    function addDaysToDateElement(element, daysToAdd) {
      var date = element.valueAsDate;
      date.setDate(date.getDate() + 1)
      element.valueAsDate = date;
    }
    

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.