Problem
I'm using AngularJS and in my view I have 7 days in a row like the pic below. The red, grey, and blue are based on a date (9/1/2013 Sunday). When I click Friday or Monday I want that date to be returned so I can reload the 0/3 with the stats for that date.
I don't need anything fancy for AngularJS I can't figure out the logic to take a base date and then switch the day out for the day that was clicked.
How do I get this to return a date?
Current base date: 9/1/2013 - Sunday
I click: Thursday
I receive: 8/29/2013 - Thursday
I click: Sunday
I receive: 9/1/2013
What it looks like
I'm currently trying to convert this function from:
JavaScript - get the first day of the week from current date
function getMonday(d) {
d = new Date(d);
var day = d.getDay(),
diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday
return new Date(d.setDate(diff));
}
getMonday(new Date()); // Mon Nov 08 2010
Solved!
I render the dates server side when I render my stats.
Using AngularJS:
My directives: http://paste.laravel.com/Nz9
My HTML template: http://paste.laravel.com/Nza
My PHP: http://paste.laravel.com/Nzc
Forget about what it looks like, let's focus on what data you have.
If I'm understanding you correctly, you have an associative array of something like:
[{'M',0},{'T',1},{'W',2},{'T',3},{'F',4},{'S',5},{'S',6}]
And you also have a base date
var base = moment('2013-09-01');
And the base is associated with the last value - the 6.
So then what you could do is something like this:
var x = 3; // I clicked on Thursday and got a 3
var target = base.subtract('days', 6-x); // move back 6-x days
That would work, but wouldn't it be much easier just to precalculate your associative array in the first place?
[{'M','2013-08-26'},
{'T','2013-08-27'},
{'W','2013-08-28'},
{'T','2013-08-29'},
{'F','2013-08-30'},
{'S','2013-08-31'},
{'S','2013-09-01'}]
Then you would already know what value to use when it was clicked.
The problem with moment's day() is that Sunday == 0, not Monday, so you have to jump one week back and use the range 1..7 for Monday..Sunday:
base = '9/1/2013'
console.log(moment(base).day(-7).day(4))
> Thu Aug 29 2013 00:00:00 GMT+0100
console.log(moment(base).day(-7).day(7))
> Sun Sep 01 2013 00:00:00 GMT+0100
Related
Im trying to get the first day of first week by given day
Correct results :
2017 = 2 Jan (Monday)
2016 = 4 Jan (Monday)
2015 = 1 Jan (Thursday)
2014 = 1 Jan (Wednesday)
2013 = 1 Jan (Tuesday)
I can get the first day of the year by :
moment().year(year).startOf('year') // All result is 1. jan XXXX
Then I tried : (correct)
moment().day(1).year(2017).week(1) // 2 Jan (Monday) (correct)
But when changed to 2016 : (wrong)
moment().day(1).year(2016).week(1) // 10 Jan (Sunday) (wrong)
Any know how to get correct results ? (Im open for pure JS date() also)
PS: Week number is based in Norway
Playground : https://jsfiddle.net/6sar7eb4/
There is no need to use loop, you can simply test if the week number is not 1 using week() that gives localized output
The output of moment#week will depend on the locale for that moment.
You have to set the locale to moment using locale() method to get start of week locale aware. If you have to show result in english you can change locale locally.
Here a working sample:
function getFirstDayOfFirstWeekByYear( year ) {
// Create moment object for the first day of the given year
let func = moment({year:year})
// Check if 1st of January is in the first week of the year
if( func.week() !== 1 ){
// If not, add a week to the first day of the current week
func.startOf('week').add(1, 'week');
}
// Return result using english locale
return func.locale('en').format('D. MMMM YYYY (dddd)')
}
// Set Norwegian Bokmål locale globally
moment.locale('nb');
// Tester
[2017, 2016, 2015, 2014, 2013].forEach(function ( year ) {
let s = '<li>' + getFirstDayOfFirstWeekByYear( year ) + '</li>'
document.getElementsByTagName('BODY')[0].innerHTML += s
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js"></script>
Anyway if your happy to do it within a loop this works
function getFirstDayOfFirstWeekByYear( year ){
let D = 1;
x = 0;
while(x !== 1){
x = moment(`${year}-01-${D}`).isoWeek();
if(x === 1 ){
return moment(`${year}-01-${D}`).format('D. MMMM YYYY (dddd)')
}
D++;
};
}
results
2. January 2017 (Monday)
4. January 2016 (Monday)
1. January 2015 (Thursday)
1. January 2014 (Wednesday)
1. January 2013 (Tuesday)
Im trying to get the first day of first week by given day
Using moment.js to get the first day of the first week of the year based on the ISO 8601 scheme, you can just use the first day of the first week of the year since the ISO week starts on Monday:
// Return a moment.js object for the first weekday of the first week
// of the year using ISO 8601 scheme
function firstDay(year) {
return moment(year + '011', 'GGGGWWE');
}
// Examples
['2015', '2016', '2017', '2018', '2019', '2020']
.forEach(function(year) {
console.log('ISO First day of ' + year + ': ' +
firstDay(year).format('dddd D MMMM, YYYY'));
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
However you seem to not want to use the ISO scheme, so if you just want to get the first day of the year that isn't a Saturday or Sunday (i.e. ignore the ISO 8601 scheme), you can do (without moment.js):
// Return Date for first day of year that is one of
// Monday to Friday
function firstDay(year) {
var d = new Date(year, 0, 1);
var day = d.getDay();
d.setDate(d.getDate() + (day%6? 0 : (++day%4)));
return d;
}
// Examples
['2015', '2016', '2017', '2018', '2019', '2020']
.forEach(function(year) {
console.log('First weekday of ' + year + ': ' + firstDay(year).toString());
});
Discussion
There are many different schemes for first day of the week and first day of the year. A commonly used scheme is ISO 8601, where the first day of the week is Monday and the first week of the year is the one in which the first Thursday appears (or the first that contains at least 4 days of the week, it's the same result).
According to ISO 8601 rules, the first day of the first week of 2019 is Monday 31 December, 2018.
If you decide to support different schemes (e.g. in Saudi Arabia the week starts on Saturday and ends on Friday, with work days Saturday to Wednesday and in the US a week is typically Sunday to Saturday with work days Monday to Friday), then you should clearly state which scheme you support and not simply assume a scheme based on the language the user has chosen. Schemes may also be based on other cultural factors such as religion, so are not necessarily region or language-based.
Which scheme should be used for an English person in Saudi Arabia? An Islamic person in Bhutan? In Saudi the official language for commerce is French, but most international discussion is in English, while the national language is Arabic. But they use the Hijri calendar, which does not align with the Georgian calendar commonly used elsewhere and is not defined by language but by religion.
There may also be differences even in the same place, with departments of the same government choosing different schemes so even locale (in the correct meaning of the term) is not a definitive indicator of which scheme to use.
If you decide to support different schemes, far better to adopt a standard scheme (like ISO 8601) and let the user change it to the one they prefer if they wish (and which the preferences in my computer and calendar application allow me to do).
I am trying to make a function that can check if a given date is in a specified week ago.
For example, if the input is <1, date object>, then it asks, if the given date is from last week. If the input is <2, date object>, then it asks if the given date is from 2 weeks ago, etc.. (0 is for current week).
Week is Sun-Sat.
this.isOnSpecifiedWeekAgo = function(weeks_ago, inputDate) {
return false;
};
But I don't want to use any libraries, and also I am not sure how to change the week of a date object. Does anyone know how to begin?
Thanks
If you want to find out a date that was a week ago, you can simply subtract 7 days from the current date:
var weekAgo = new Date();
weekAgo.setDate(weekAgo.getDate() - 7);
console.log(weekAgo.toLocaleString());
If you want to find out if a date is in a specific week, you'll need to:
Work out the start date for that week
Work out the end date for that week
See if the date is on or after the start and on or before the end
Since your weeks are Sunday to Saturday, you can get the first day of the week from:
var weekStart = new Date();
weekStart.setDate(weekStart.getDate() - weekStart.getDay());
console.log(weekStart.toLocaleString());
The time should be zeroed, then a new date created for 7 days later. That will be midnight at the start of the following Sunday, which is identical to midnight at the end of the following Saturday. So a function might look like:
function wasWeeksAgo(weeksAgo, date) {
// Create a date
var weekStart = new Date();
// Set time to 00:00:00
weekStart.setHours(0,0,0,0);
// Set to previous Sunday
weekStart.setDate(weekStart.getDate() - weekStart.getDay());
// Set to Sunday on weeksAgo
weekStart.setDate(weekStart.getDate() - 7*weeksAgo)
// Create date for following Saturday at 24:00:00
var weekEnd = new Date(+weekStart);
weekEnd.setDate(weekEnd.getDate() + 7);
// See if date is in that week
return date >= weekStart && date <= weekEnd;
}
// Test if dates in week before today (1 Nov 2016)
// 1 Oct 24 Oct
[new Date(2016,9,1), new Date(2016,9,24)].forEach(function(date) {
console.log(date.toLocaleString() + ' ' + wasWeeksAgo(1, date));
});
Use moment.js http://momentjs.com/docs/#/manipulating/subtract/
We use it a lot and its a great lib.
I have this code:
var nextDate = new Date("2016 01 31");
nextDate.setMonth(nextDate.getMonth() + 1);
I'm expecting the result to be Feb 28 2016, but it shows Mar 02 2016 instead.
Why? Is there any solution for it?
There is only 29 day in February, therefore, February 31 February will translate to Mars 2.
You need to update the days in your date object to the last day of that month. You can get the last day of the month by specifying a function that sets the date to 0:
function daysInMonth(month,year) {
return new Date(year, month, 0).getDate();
}
This is because February has 29 days, and when you set new month from January, which has 31 day, to February then the difference of the days are transferred to another month.
Easy way to do it is just create new Date instance.
You might need to implement some logic to get corresponding dates right
Possible work around with a helper function: after setMonth, check if the results doesn't contain a month equal to the expected month and if so, use setDate(0), which sets the date to last day of the previous month. e.g.
Date.prototype.addMonths = function(months){
var m = this.getMonth() + (months || 1);
this.setMonth(m);
if(this.getMonth() !== (m % 11)) //11: month is 0 based
this.setDate(0);
}
var nextDate = new Date("2016 01 31");
nextDate.addMonths(1);
document.writeln(nextDate);
months || 1 only is meant to have a default value if no month was submitted. m % 11 is needed in case of year transitions. 11 and not 12 because javascripts month (and thus getMonth) is 0 based.
In this sample code to convert a string to a date:
function stringToDate(){
var edate = "2015-06-01";
Logger.log(edate);
var input = edate.split('-');
var date = new Date();
date.setUTCFullYear(input[0],input[1] - 1,input[2]);
Logger.log(date);
}
Logging the date returns "Mon Jun 01 20:07:45 GMT+01:00 2015", which is correct, as the month '06' - 1 = 5 corresponds to the month of June for the this.
However, this almost identical function:
function stringToDate2(){
var edate = "2015-06-01";
Logger.log(edate);
var input = edate.split('-');
var date = new Date();
date.setUTCFullYear(input[0]);
date.setUTCMonth(input[1] - 1);
date.setUTCDate(input[2]);
Logger.log(date);
}
Returns "Wed Jul 01 20:10:04 GMT+01:00 2015". Some other values return equally screwy results. Why do I get a different result for 'setUTCMonth' then for 'setUTCFullYear'?
Set the Date before the Month
date.setUTCFullYear(input[0]);
date.setUTCDate(input[2]);
date.setUTCMonth(input[1] - 1);
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/setUTCMonth
If a parameter you specify is outside of the expected range,
setUTCMonth() attempts to update the date information in the Date
object accordingly. For example, if you use 15 for monthValue, the
year will be incremented by 1, and 3 will be used for month.
Each of the UTC functions has a similar note about out of range values.
So because of this:
new Date() gets the current date, and thus today being 5/31 the date is 31.
There are some months without a 31st date, so 31 is outside the range for date so it is updated accordingly.
So if you try to set the month for say February without changing the date first,
The date would be 2/31/2015, but February only has 28 days this year so it rolls over to 3/03/2015
And in your case, if you try to set it for June, 6/31/2015, June never has a 31st date so again it rolls over to 7/01/2015. And so on.
So change the date first like I show above or set a default date when you create it:
new Date("01/01/2015")
I'm using this script located here: http://www.javascriptkit.com/script/script2/dyndateselector.shtml
If you try it, and go to any of April, June, September or November, you will notice that the day of the week columns are incorrect. Here's a list of incorrect data (the x starts y stuff is showing the following month.)
Bugged months:
4/April (starts Sunday instead of Friday)
May starts Sunday
6/June (starts Friday instead of Wednesday)
July starts Friday
9/September (starts Saturday instead of Thursday)
October starts Saturday
11/November (starts Thursday instead of Tuesday)
December starts Thursday
You'll notice that every bugged month is starting with the day of the following month, yet all the other months seem to be correct.
I can't find anything on this problem. Anyone able to help? The actual Javascript alone can be found here, and the getDay() method occurs on line 125: http://pastebin.com/0zuBYrzv
I've tested in both Firefox and Chrome.
Here's some very simple code to demonstrate the issue:
<script>
var d = new Date();
d.setMonth(5);
d.setFullYear(2011);
d.setDate(1);
alert(d.getDay());
</script>
This will create an alert with the message "5", meaning Friday (5+1 = 6, Friday is the 6th day of the week,) when in fact Wednesday is the start of the week.
This is actually pretty interesting as i am guessing that tomorrow your original code will work as you want again.
What i think is happening is you are creating a new Date and that will automaticly initialize to today (31th of may).
Then you set the Month to June by which you basically say make it 31th of June. This date doesn't exist so javascript will turn it into 1th of July.
Finally you set the Date but since your month is not anymore what you want it to be the results will be wrong.
Looks like 0 is january and 11 is december.
Apparently JavaScript doesn't like it if I set the month, full year, then day. What I must do is set them all in one function, like so:
<script>
var d = new Date();
d.setFullYear(2011, 5, 1);
alert(d.getDay());
</script>
I think this is a bug in Javascript's Date Object.
Please take a look at the following code.
(I'm using w3school's JSref tool online to see it quickly.)
Please note, the ways used below are told by w3 schools themselves.
Some examples of instantiating a date:
var today = new Date()
var d1 = new Date("October 13, 1975 11:13:00")
var d2 = new Date(79,5,24) (//THIS IS WRONG - unexpected results!!!)
var d3 = new Date(79,5,24,11,33,0)
So please be careful when using this Date object, looks like certain ways of instantiating dates are better than others.
<script type="text/javascript">
function whatDayIsToday(date)
{
var weekday=new Array(7);
weekday[0]="Sunday";
weekday[1]="Monday";
weekday[2]="Tuesday";
weekday[3]="Wednesday";
weekday[4]="Thursday";
weekday[5]="Friday";
weekday[6]="Saturday";
document.write("Today is " + weekday[date.getDay()] + ", <br />");
document.write("the " + date.getDay() + getSuffix(date.getDay()) + " day of the week. <br /><br />")
}
function getSuffix(num)
{
return (num>3)?"th":(num==3)?"rd":(num==2)?"nd":(num==1)?"st":"";
}
//CORRECT
var d3 = new Date("01/01/2011");
whatDayIsToday(d3);
//CORRECT
var d2 = new Date("01/01/2011");
whatDayIsToday(d2);
//DOESN'T WORK
var d5 = new Date("1-1-2011");
whatDayIsToday(d5);
//WRONG
var d4 = new Date("2011", "01", "01");
whatDayIsToday(d4);
//DAY OF WEEK IS WRONG
var d = new Date(2011, 1, 1);
whatDayIsToday(d);
//DAY OF WEEK IS ALSO WRONG
var d0 = new Date(11, 1, 1);
whatDayIsToday(d0);
</script>
outputs (all using some format of 1/1/2011) are:
Today is Saturday,
the 6th day of the week. (CORRECT, January first this year was a saturday)
Today is Saturday,
the 6nd day of the week. (CORRECT)
Today is undefined,
the NaNnd day of the week. (WRONG FORMATTING, DOESN'T WORK - EXPECTED)
Today is Tuesday,
the 2nd day of the week. (WRONG - UNEXPECTED)
Today is Tuesday,
the 2nd day of the week. (WRONG - UNEXPECTED)
Today is Wednesday,
the 3nd day of the week. (WRONG - UNEXPECTED)
Based on the other answers to this question, I'm guessing it has to do with the day I'm on currently (8/26/2011) - this would be my starting new Date() and the days and/or years getting applied in the wrong order.
However, it sure would be nice if this thing worked!
This is the typical wrong approach:
var days = ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"];
var d = new Date();
d.setFullYear(selectYear.options[selectYear.selectedIndex].value);
d.setMonth(selectMonth.options[selectMonth.selectedIndex].value-1);
d.setDate(selectDay.options[selectDay.selectedIndex].value);
alert(days[d.getDay()]);
It will work most of the time. But it will have problems with when current date is 31 and when trying to set date to 31 for when set at a month with less than 31 days.
This is a good way:
var days = ["Söndag", "Måndag", "Tisdag", "Onsdag", "Torsdag", "Fredag", "Lördag"];
var d = new Date(0); // solves all problems for existing dates
d.setFullYear(selectYear.options[selectYear.selectedIndex].value);
d.setMonth(selectMonth.options[selectMonth.selectedIndex].value-1);
d.setDate(selectDay.options[selectDay.selectedIndex].value);
if( d.getDate() == selectDay.options[selectDay.selectedIndex].value ) {
alert(days[d.getDay()]);
}
else {
alert("this date doesn't exist"); // date was changed cuz date didn't exist
}
Constructing the date with new Date(0) sets the date to 1 jan, this is good because the date is not 31st and january has 31 days which give us the space we need. It wont fail on the 31st and we don't need to set the datas in any special order. It will always works.
If the user sets month to september (30 days) and date to 31 the data object will hold either 1 oct or 1 sep (depending on which order you set them in). Which is irrelevant because they are both wrong. A simple check if the date is what we set it to will tell us if the date is a existing date, if not we can tell the user this.