How to calculate month from number of days in JavaScript - javascript

So basically I have done a calculation that increments a clock time:
function Clock(year,month,day,hours,minutes,seconds){
if(seconds !== null){
this.seconds = seconds;
}
if(minutes !== null){
this.minutes = minutes;
}
if(hours !== null){
this.hours = hours;
}
if(day !== null){
this.day = day;
}
if(month !== null){
this.month = month;
}
if(year !== null){
this.year = year;
}
}
function incrementClock(){
clock.seconds++;
if (clock.seconds >=60) {
clock.seconds = 0;
clock.minutes++;
if (clock.minutes >=60) {
clock.minutes = 0;
clock.hours++;
if (clock.hours >=24) {
clock.hours = 0;
clock.days++;
}
}
}
}
function showClock(){
//prints clock in format yyyy/mm/dd hh:mm:ss
}
This would increment the seconds, minutes, hours and days accordingly...
So if I call print the clock each second it would look like this:
var c = new Clock(2014,04,01,12,13,01);
showClock();
2014/4/1 12:13:1
I get stuck on the month part...
My question is how would I go about checking if a month has passed as there are different amount of days each month?
EDIT
I am creating my own minified Date function... so please don't recommend using Date objects as I am trying to implement my own

Is this what you're looking for?
function incrementClock(){
clock.seconds++;
if (clock.seconds >=60) {
clock.seconds = 0;
clock.minutes++;
if (clock.minutes >=60) {
clock.minutes = 0;
clock.hours++;
if (clock.hours >=24) {
clock.hours = 0;
clock.days++;
var months = [31,((clock.year%4==0)&&((clock.year%100!=0)||(clock.year%400==0)))?29:28,31,30,31,30,31,31,30,31,30,31];
if (clock.days>months[clock.month-1]){
clock.days = 0;
clock.months++;
}
}
}
}
}
This line:
var months = [31,((clock.year%4==0)&&((clock.year%100!=0)||(clock.year%400==0)))?29:28,31,30,31,30,31,31,30,31,30,31];
creates an array of the months and the days in each month. Thus it is easy to determine the amount of days per month like so:
days_in_jan = months[0]
days_in_feb = months[1]
...
days_in_dec = months[11]

You don't. You don't increment anything actually. If you want your own clock, that's fine, but you still need to access the current time using a Date object, so when you want to know how much time has elapsed, get a new Date object and figure it out:
pseudo structure:
Class Clock
- start date
- function timeElapsed
- elapsed = now - start date
In that function, compare the month, day, etc.
And honestly, if you don't like that answer you're on your own, as the answer to "how do I do this random thing as purely a thought exercise" is exactly that -- a thought exercise. There's no real point to it, so it shouldn't be asked or answered on SO.

As others have done, I would suggest using the Date object, or a date library like MomentJS, but it seems like you want to do the implementation yourself as an exercise. In that case, your code will need to know how many days are in each month if it is going to do the calculation correctly. Consider including in your code an array of the months' lengths:
var monthLengths = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31];
You'll also need a function to determine whether or not it's a leap year:
function isLeapYear(year) {
return (year % 4 == 0) && ((year % 100 != 0) || (year % 400 == 0));
}
Armed with those, you should be able to tell if a date has exceeded its month by checking the array to know how many days are in that month, and (if it's February) using the leap year function to determine if you should count 29 days for February.

Related

Can I use comparison and logical operators for time inputs in Javascript? [duplicate]

I'm trying to write a statement that says "if time is this and less than that then". I can use get hours and get min. However, I'm having problems combining a time such as 9:30.
Example,
var now = new Date();
var hour = now.getHours();
var day = now.getDay();
var mintues = now.getMinutes();
if (day == 0 && hour >= 9 && hour <= 11 && mintues >= 30) {
document.write(now);
}
This only if the time is less between 9:30 10. As soon as the clock hits 10 the minutes are then < 30 and the script breaks.
Any thoughts on how to better incorporate the time function to make this theory work?
Thanks,
use new Date().getTime() returns milliseconds for much easier comparison. This way there is no need to check hour, min, second, millisecond. Fiddle link
var d930 = new Date(2010, 12, 21, 9, 30, 0, 0), // today 9:30:00:000
d931 = new Date(2010, 12, 21, 9, 31, 0, 0), // today 9:31:00:000
t930 = d930.getTime(),
t931 = d931.getTime();
console.log(t931 > t930);
This way your code can check against a static 9:30 time.
var time930 = new Date(2010, 12, 21, 9, 30, 0, 0).getTime(),
sunday = 0,
now = new Date();
if(now.getDay() == sunday && now.getTime() >= time930){
/* do stuff */
}
You have a few typos and basic javascript errors.
Might wanna brush up on the basics.
W3Schools is where I learned all I know.
It works fine if you fix them...
var now = new Date();
var hour = now.getHours();
var day = now.getDay();
var minutes = now.getMinutes();
if(day == 0 && hour == 9 && minutes < 30 && minutes > 10 || day == 0 && hour == 9)
document.write('Time is between 9:10 and 9:30');
Think of the if statement as basic logic.
If the day is Sunday(0)
AND the hour is 9
AND the minutes are greater than 10
AND the minutes are less than 10
OR the day is Sunday(0)
AND the hour is before 9.
var now = new Date();
var closeTime = new Date();
closeTime.setHours(9); closeTime.setMinutes(30);
console.log(now, closeTime, now.getTime() >= closeTime.getTime());
close time is based on today, then we just change the hours and minutes to 9:30.
I made this solution simple and easy to read (thus easy to adjust).
// we need a function that makes hours and minutes a two digit number
Object.prototype.twoDigits = function () {
return ("0" + this).slice(-2);
}
// get current date and time
let now = new Date();
// compile the current hour and minutes in the format 09:35
timeOfDay = now.getHours().twoDigits() + ':' + now.getMinutes().twoDigits();
// test if timeOfDay is within a given time frame
if ('09:30' <= timeOfDay && timeOfDay <= '11:30') {
console.log('inside time frame');
} else {
console.log('outside time frame');
}
I had a similar problem to solve today, I setup a little component that returns if a place of business is open or not. Got the time by dividing the minutes by 100 then adding it to the hours. So 8:30 is represented as 8.3
let d = new Date()
let day = d.getDay()
let hours = d.getHours()
let minutes = d.getMinutes() / 100
let time = hours + minutes
if (day == 1) {
if (time > 8.3 && time < 17.3) {
setIsOpen(true)
} else {
setIsOpen(false)
}
}
if the hour is less than 9, true
or
if hour is 9 and minutes lt 30, true
so that would look like
if ((hour < 9) || (hour == 9 && minutes < 30))
Use words to figure out your logic. Symbols are just shortcuts.
One way is to do a direct comparison on date objects. Choose an arbitrary year, month and day, and then incorporate your times as follows:
var older = new Date("1980-01-01 12:15");
var newer = new Date("1980-01-01 12:30");
if (newer > older){
alert("Newer time is newer");
} else {
alert ("The time is not newer");
}
The MDC documentation on the Date object will help with some more details. The bottom line is that if you want to compare times, you don't actually need to call any methods on the objects, and it's possible to directly compare them. The date() object can take a variety of strings to assign a new time to the returned instance, these are from the MDC documentation:
today = new Date();
birthday = new Date("December 17, 1995 03:24:00");
birthday = new Date(1995,11,17);
birthday = new Date(1995,11,17,3,24,0);
As you can see, it's pretty simple. Don't complicate, and have a look through the documentation :)
While we're here, here's a test using your example:
var base = new Date("1980-01-01 9:30");
var test = new Date("1980-01-01 9:30:01");
if (test >= base){
alert("test time is newer or equal to base time");
} else {
alert ("test time is older than 9.30");
}
Try this:
var now = new Date();
var hour = now.getHours();
var mintues = now.getMinutes();
if(
(hour*60 + mintues) > 570 &&
hour <= 11
)
{
document.write(now);
}
I don't quite fully understand your question but hope this helps.
c = new Date();
nhour = c.getHours();
nmin = c.getMinutes();
if(nmin <= 9) {
nmin = "0" + nmin;
}
if(nhour <= 9) {
nhour = "0" + nhour;
}
newtime = nhour + "" + nmin;
if(newtime <= 0930){
alert("It is before 9:30am or earlier");
}

How to calculate new date after date validation?

I'm using Elian Ebbing's data validation code from here and after validation, I'd like to take the date entered and return a new date for X amount of months later. For example, if I entered 06/09/2019, I would then like the code to return the correct new date that's 6 months later, which would be 12/6/2019.
Can someone please help guide me through the process of accomplishing this? I have been trying different methods of reusing the original code to get the results that I want, however I have been at this since July 2nd and have concluded I just can't figure this out on my own. I am completely stumped.
Lastly, my deepest apologies in advance that I didn't just comment on the original thread for Mr. Ebbing's code and ask for help, but unfortunately I did not have enough reputation points to do so.
If you are not sure that it is good to use some library (moment.js). If you want to find something already discovered, be ready to bump your head.
// Elian Ebbing validator
function isValidDate(dateString) {
// First check for the pattern
if(!/^\d{1,2}\/\d{1,2}\/\d{4}$/.test(dateString))
return false;
// Parse the date parts to integers
var parts = dateString.split("/");
var day = parseInt(parts[1], 10);
var month = parseInt(parts[0], 10);
var year = parseInt(parts[2], 10);
// Check the ranges of month and year
if(year < 1000 || year > 3000 || month == 0 || month > 12)
return false;
var monthLength = [ 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 ];
// Adjust for leap years
if(year % 400 == 0 || (year % 100 != 0 && year % 4 == 0))
monthLength[1] = 29;
// Check the range of the day
return day > 0 && day <= monthLength[month - 1];
}
// if you want to change date format
function formatDate(date) {
var d = new Date(date),
month = '' + (d.getMonth() + 1), // monts start form 0 so for result 06/01/2019
day = '' + d.getDate(),
year = d.getFullYear();
if (month.length < 2) {
month = '0' + month;
}
if (day.length < 2) {
day = '0' + day;
}
return [month, day, year].join('/');
}
// increment Date with count of months
function incrementDate(date, counter = 0) {
if (isValidDate(start_date_value)) {
var newDate = new Date(date);
newDate.setMonth(newDate.getMonth() + counter);
console.log(formatDate(newDate));
}
}
var start_date_value = "01/01/2019";
incrementDate(start_date_value, 5) ; // 06/01/2019

Display div based on remote timezone and dates

I'm trying to display a chat div that displays between the hours of 8am-6pm Monday to Friday "Online" or show nothing if offline, based on the Eastern Time Zone (NYC), so that customers from Beijing will see Online or Offline based on these hours.
Simply need to show() or hide() the div. So far I have the hours, but I'm not sure how to get them to be in relation to the user time-zone.
$(document).ready(function () {
var start = new Date();
var end = new Date();
var time = new Date().getTime();
if (time > start.setHours(8,00) && time < end.setHours(18,00)) {
$('.online').show();
}
else {
$('.offline').hide();
}
});
The previous answer (seen in edit history) was to use the offset from UTC, however that isn't going to be an option if you want to support Daylight Savings; which is an important thing to do.
As such, the modification to the previous suggestion completely removes the use of UTC. To support daylight savings, the only proper way to get the time from EST is going to be to set the locale to that location, read the time, set up a new date object (which will technically be set up in the client local, but all we really want from it are the day and hour response from the Date object so we will ignore that technicality).
This is done by passing an object with the toLocaleString call which specifies the timezone, and then constructing a new date with the result of that.
var NYDate = new Date(new Date().toLocaleString("en-US", {timeZone: "America/New_York"}));
var NYHour = NYDate.getHours();
var NYDay = NYDate.getDay()
if (NYHour >= 8 && NYHour <= 18 &&
NYDay > 0 && NYDay < 6) {
$('.online').show();
}else {
$('.online').hide();
}
.online {
display: none;
color: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="online">Online</div>
No JavaScript needed. You should do this from the server side. (The customer doesn’t tell the store when it’s open, the store tells the customer!)
Assuming your HTML is being generated by some server-side language (PHP, Ruby, etc), set the program to use New York time, and simply calculate if you’re within the “open” times. If you’re open, generate the Chat div. if you’re closed... don’t.
(Or alternately, show/hide it via CSS and classes)
Turns out that this is not a completely trivial task using JavaScript (as noted in the answer from #StephenR, this may be easier to deal with server side). And as noted in some of the comments, using a library may be the better js approach.
That said, after thinking a bit about the comments from #RobG regarding varying browser support for options like timeZone in toLocaleString, I was curious what it would take to solve this another way (makes me grateful for the various js date libraries). Snippet below...
const getOffset = (month, date, day, hour) => {
// assume EST offset
let offset = 5;
// adjust to EST offset as needed
if ((month > 2 && month < 10) || (month === 2 && date > 14)) {
offset = 4;
} else if (month === 2 && date > 7 && date < 15) {
if ((day && date - day > 7) || (day === 0 && hour - offset >= 2)) {
offset = 4;
}
} else if (month === 10 && date < 8) {
if ((day && date - day < 0) || (day === 0 && hour - offset < 1)) {
offset = 4;
}
}
return offset;
};
const isOnline = () => {
const dt = new Date(); // current datetime
let year = dt.getUTCFullYear(); // utc year
let month = dt.getUTCMonth(); // utc month (jan is 0)
let date = dt.getUTCDate(); // utc date
let hour = dt.getUTCHours(); // utc hours (midnight is 0)
let day = dt.getUTCDay(); // utc weekday (sunday is 0)
let offset = getOffset(month, date, day, hour);
if (hour - offset < 0) {
hour = 24 + hour - offset;
day = day ? day - 1 : 6;
if (date === 1) {
if (!month) {
year -= 1;
month = 11;
} else {
month -= 1;
}
date = new Date(year, month + 1, 0).getDate();
} else {
date -= 1;
}
} else {
hour -= offset;
}
if (day > 0 && day < 6 && hour > 7 && hour < 19) {
return true;
}
return false;
};
if (isOnline()) {
console.log('online'); // handle online
} else {
console.log('offline'); // handle offline
}

How do I change the timezone/timestamp of this jquery plugin?

I'm using this plugin called timeago found here: timeago.yarp.com
It works great, except that it operates in what appears to be a different timezone. I live in Eastern US (Philadelphia timezone) and when I put the exact time EST into the timeago plugin (say 2011-05-28, 13:47:18), it reprints as four hours later on my html page. When I write 2011-05-28, 17:47:18 (four hours later than my actual time from where I live), THEN it reprints as "less than a minute ago"
Here's the jquery plugin code:
(function($) {
$.timeago = function(timestamp) {
if (timestamp instanceof Date) {
return inWords(timestamp);
} else if (typeof timestamp === "string") {
return inWords($.timeago.parse(timestamp));
} else {
return inWords($.timeago.datetime(timestamp));
}
};
var $t = $.timeago;
$.extend($.timeago, {
settings: {
refreshMillis: 60000,
allowFuture: false,
strings: {
prefixAgo: "added",
prefixFromNow: "added",
suffixAgo: "ago",
suffixFromNow: "from now",
seconds: "less than a minute",
minute: "about a minute",
minutes: "%d minutes",
hour: "about an hour",
hours: "about %d hours",
day: "a day",
days: "%d days",
month: "about a month",
months: "%d months",
year: "about a year",
years: "%d years",
numbers: []
}
},
inWords: function(distanceMillis) {
var $l = this.settings.strings;
var prefix = $l.prefixAgo;
var suffix = $l.suffixAgo;
if (this.settings.allowFuture) {
if (distanceMillis < 0) {
prefix = $l.prefixFromNow;
suffix = $l.suffixFromNow;
}
distanceMillis = Math.abs(distanceMillis);
}
var seconds = distanceMillis / 1000;
var minutes = seconds / 60;
var hours = minutes / 60;
var days = hours / 24;
var years = days / 365;
function substitute(stringOrFunction, number) {
var string = $.isFunction(stringOrFunction) ? stringOrFunction(number, distanceMillis) : stringOrFunction;
var value = ($l.numbers && $l.numbers[number]) || number;
return string.replace(/%d/i, value);
}
var words = seconds < 45 && substitute($l.seconds, Math.round(seconds)) ||
seconds < 90 && substitute($l.minute, 1) ||
minutes < 45 && substitute($l.minutes, Math.round(minutes)) ||
minutes < 90 && substitute($l.hour, 1) ||
hours < 24 && substitute($l.hours, Math.round(hours)) ||
hours < 48 && substitute($l.day, 1) ||
days < 30 && substitute($l.days, Math.floor(days)) ||
days < 60 && substitute($l.month, 1) ||
days < 365 && substitute($l.months, Math.floor(days / 30)) ||
years < 2 && substitute($l.year, 1) ||
substitute($l.years, Math.floor(years));
return $.trim([prefix, words, suffix].join(" "));
},
parse: function(iso8601) {
var s = $.trim(iso8601);
s = s.replace(/\.\d\d\d+/,""); // remove milliseconds
s = s.replace(/-/,"/").replace(/-/,"/");
s = s.replace(/T/," ").replace(/Z/," UTC");
s = s.replace(/([\+\-]\d\d)\:?(\d\d)/," $1$2"); // -04:00 -> -0400
return new Date(s);
},
datetime: function(elem) {
// jQuery's `is()` doesn't play well with HTML5 in IE
var isTime = $(elem).get(0).tagName.toLowerCase() === "time"; // $(elem).is("time");
var iso8601 = isTime ? $(elem).attr("datetime") : $(elem).attr("title");
return $t.parse(iso8601);
}
});
$.fn.timeago = function() {
var self = this;
self.each(refresh);
var $s = $t.settings;
if ($s.refreshMillis > 0) {
setInterval(function() { self.each(refresh); }, $s.refreshMillis);
}
return self;
};
function refresh() {
var data = prepareData(this);
if (!isNaN(data.datetime)) {
$(this).text(inWords(data.datetime));
}
return this;
}
function prepareData(element) {
element = $(element);
if (!element.data("timeago")) {
element.data("timeago", { datetime: $t.datetime(element) });
var text = $.trim(element.text());
if (text.length > 0) {
element.attr("title", text);
}
}
return element.data("timeago");
}
function inWords(date) {
return $t.inWords(distance(date));
}
function distance(date) {
return (new Date().getTime() - date.getTime());
}
// fix for IE6 suckage
document.createElement("abbr");
document.createElement("time");
}(jQuery));
I realize this problem is something very minor and can be easily fixed if I were to just remember the plugin works on a 4 hour delay, but I'd still like to know the answer if possible to provide.
Thanks!
Updated
I'm going to give this a shot but I must add the disclaimer that I'm a little fuzzy on this myself so I might be quite wrong!
The plugin expects the time in the ISO 8601 format which can also include offset information. I've now tried using the plugin and this is what I see (at 14:42 EDT, about 3 minutes from the test time string):
When a trailing Z is used, indicating Zulu time or an offset of 0 from UTC, the plugin interprets it as UTC (obviously) and when printing the relative time string, it takes into consideration your actual timezone. This causes the extra 4 hours to be added (EST is UTC-5 (UTC-4 when following DST, like now)).
2011-05-28T14:39:33Z prints as about 4 hours ago
When a trailing Z is not used, the plugin interprets the time specified according to your timezone and it seems to work just fine (as long as the timezone for the timestamp and the timezone you're viewing this timestamp in are the same). This is in line with what the Wikipedia article has to say:
If no UTC relation information is given with a time representation, the time is assumed to be in local time. While it may be safe to assume local time when communicating in the same time zone, it is ambiguous when used in communicating across different time zones. It is usually preferable to indicate a time zone (zone designator) using the standard’s notation.
This would not be a recommended way since it's going to mess up the times when viewed from elsewhere since the timestamp will be interpreted as being the timestamp for that timezone which is incorrect.
2011-05-28T14:39:33 prints as 3 minutes ago
When a trailing Z is specified along with the timezone offset (in the format of hh:mm, only hh seems to be ignored), it still seems to work just fine.
2011-05-28T14:39:33Z-04:00 prints as 3 minutes ago
You can see a working example here: http://jsfiddle.net/nogoodatcoding/SVgck/
You shouldn't be changing the timezone/offset of the plugin itself since that will cause visitors from other timezones to see incorrect values.
One fix is to also specify the timezone offset in your date-time strings: 2011-05-28, 13:47:18Z-04:00 - in a sense, a more complete description of the time since it also includes the UTC offset information.
Depending on how you're generating this page (if it's not just static HTML), the other option is to fix your server-side code so that the date-time string it outputs is in the UTC format - if not built in, you should be able to find a library that does the conversion from a timestamp in your local timezone into UTC. This is how sites I've seen do it - for example, the timestamps here on StackOverflow (or on Twitter and Facebook) are in UTC time - they are then formatted differently based on the user's timezone.
Hey, I use this plugin. It's not the javascript you have to edit. Look for the php file, in wordpress it's called 'wpTimeAgo.php' it should be something similar to that.
In that file look for this:
var $_gmtOffset = '';
Add a number there, I believe that should do the trick.
If you're using timeago in the .NET world, you'll find it's very fussy about the offset it gets. z and zz won't work, it needs to be zzz and should include the delimiting big "Z" and "T".
For example:
string.Format("{0}Z{1:%zzz}", DateTime.Now.ToString("s"), DateTime.Now);
This displays as:
2013-01-06T12:46:28Z-08:00

Will this JS time code work? Can I make it better?

I'm displaying a message between Saturday at 6pm and Sunday 4am. The last time I had to do this it didn't work because I didn't take into account UTC time going negative when changing it to NYC time.
I am doing the math right (displaying at the appropriate times)?Should I put the UTC conversion code into its own function? Is this the worst js you've ever seen?
-- jquery is called --
$(document).ready(function() {
var dayTime = new Date();
var day = dayTime.getUTCDay();
var hour = dayTime.getUTCHours();
//alert(day.toString()+" "+hour.toString());
if (hour >= 5){
hour = hour-5;
}
else{
hour = hour+19;
if(day > 0){
day--;
}
else{
day = 6;
}
}
//alert(day.toString()+" "+hour.toString());
if ((day == 6 && hour >= 18) || (day == 0 && hour < 4)){
}
else{
$('#warning').hide(); //Want this message to show if js is disabled as well
}
});
Why do you even need that UTC stuff? Just work with local time:
var day = dayTime.getDay();
var hour = dayTime.getHours();
And you can clean up that conditional a bit too:
if (!(day == 6 && hour >= 18) && !(day == 0 && hour < 4)) {
$('#warning').hide();
}
This should get you your server's time:
var dayTime = new Date();
localOffset = dayTime.getTimezoneOffset() * 60000;
serverOffset = 5 * 60 * 60000;
dayTime = new Date(dayTime.getTime() + (localOffset - serverOffset));
Play around with that "5" in the server offset; it's the hours. It may need to be a -5; I'm not really sure.
Also, that's going to break every daylight savings. You'll have to detect that somehow and modify serverOffset.

Categories