How to make custom time and date? - date

I have looked at this code and they just seem to simply update theirs every day with the HTML, but I know there's a way to make a custom date by altering Monday to be Morndas, Sunday to be Sundas, January as Morning Star, etc. How would I go about coding this for my own website, as it's a cool little feature to have on an Elder Scrolls website, and I am not always available to update it every night at midnight.
Thanks

I think this is best done using server side scripting, like PHP. But below I've given a Javascript implementation which you can easily embed. Once you learn about server side scripting, it should be trivial to translate this code to another language.
window.addEventListener('DOMContentLoaded', function() {
// Function to determine the postfix of the month number
function numberPostFix(nr) {
nr = nr % 100;
if (nr >= 10 && nr < 20) return 'th';
nr = nr % 10;
if (nr == 1) return 'st';
if (nr == 2) return 'nd';
if (nr == 3) return 'rd';
return 'th';
}
// Arrays of custom month names.
var monthNames = [
"Morning Star",
"Sun's Dawn",
"First Seed",
"Rain's Hand",
"Second Seed",
"Mid Year",
"Sun's Height",
"Last Seed",
"Hearthfire",
"Frostfall",
"Sun's Dusk",
"Evening Star"
];
// Array of custom weekday names.
var dayNames = [
"Sundas",
"Morndas",
"Tirdas",
"Middas",
"Turdas",
"Fredas",
"Loredas"
];
// Get all relevant parts.
var date = new Date();
var month = date.getMonth();
var monthday = date.getDate();
var weekday = date.getDay();
// Construct the day text.
var dateHtml = "Today is " + dayNames[weekday] + ", " + monthday + "<sup>" + numberPostFix(monthday) + "</sup> of " + monthNames[month];
// Write to document.
document.getElementById('date').innerHTML = dateHtml;
});
<header>
<h2>Welcome, this is your page header.</h2>
<span id="date"></span>
</header>

Related

Google Sheets: Session.getEffectiveUser() returns wrong values... twice

So what I'm trying to do is to log the edits of a spreadsheet on a corresponding column.
http://i.imgur.com/P8qrJOe.gif
The last column is the autogenerated text from the embedded script.
Here's the code:
function triggeredEdit () {
// set sheet variables
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var activeRange = activeSheet.getActiveRange();
// last updated
// LAST EDITED FOR SCRIPTS (check M3 if "Latest Row Modifications")
if (activeSheet.getRange("M3").getValue() == "Latest Row Modifications") {
for (var i = 1; i <= activeRange.getHeight(); i++) {
// modified TL column
if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 6 && activeRange.getLastColumn() <= 6) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 13)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
// modified TLC column
else if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 8 && activeRange.getLastColumn() <= 8) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 14)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
// modified edit column
else if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 10 && activeRange.getLastColumn() <= 10) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 15)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
// modified QC column
else if (activeRange.getCell(i, 1).getRow() > 4 && activeRange.getColumn() >= 11 && activeRange.getLastColumn() <= 11) {
activeSheet.getRange(activeRange.getCell(i, 1).getRow(), 16)
.setValue(Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
}
}
}`
The function triggeredEdit is run through a project trigger, which is also dynamically created in another function. As you can see in the gif, it seems like the triggeredEdit is called twice (since it changes twice). What's worse is that the correct email to be displayed is the first one, but then it gets replaced with the wrong one.
How do I go around fixing this? I'm quite stuck with this problem.
From what you explained in the comments It seems that you have 2 triggers on that spreadsheet that work simultaneously.
When you call Session.getEffectiveUser in a function triggered by onEdit, it returns the email of the user that installed the trigger. If you want to get the user at the keyboard then use Session.getActiveUser. Note that this will work only if you are in a domain, nothing is returned in normal gmail accounts.
To test that I used this small code :
function triggeredEdit () {
var activeSheet = SpreadsheetApp.getActiveSpreadsheet().getActiveSheet();
var activeRange = activeSheet.getActiveRange();
Logger.log('xx');
activeSheet.getRange(1, 1).setValue('effective = '+Session.getEffectiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
activeSheet.getRange(1, 3).setValue('active = '+Session.getActiveUser() + "\n" + Utilities.formatDate(new Date(), "GMT", "dd MMM YY, HH:mm:ss"));
}
and here is what I get when I edit a cell (Serge created the trigger and Lambda was the user at the keyboard.
:
If I use the spreadsheet with my gmail account then I get this result below : no value as activeUser
and, finally, if I create a second trigger with my gmail account I have a double instance like yours.(I didn't capture the gif, sorry ;)
All this seems quite logical after all when I refer to the documentation about script authorization : triggers run under the authority of the user that creates it.
The soluion in your case will probably to change the way the triggers are created to avoid that anyone can do it... or try to filter execution in some way but I'm not sure that can be done.

How to calculate the time difference between 2 date time values

I am trying to calculate the time difference between 2 date time strings.
I have 2 inputs where the input string is something like this "1:00 PM" and the second one "3:15 PM". I want to know the time difference. So for the above example I want to display 3.15
What I have done:
Converted the time to a 24 hours format. So "1:00 PM" becomes "13:00:00"
Appended the new time to a date like so: new Date("1970-1-1 13:00:00")
Calculated the difference like so:
Code:
var total = Math.round(((new Date("1970-1-1 " + end_time) -
new Date("1970-1-1 " + start_time) ) / 1000 / 3600) , 2 )
But the total is always returning integers and not decimals, so the difference between "1:00 PM" and "3:15 PM" is 2 not 2.15.
I have also tried this (using jQuery, but that is irrelevant):
$('#to_ad,#from_ad').change(function(){
$('#total_ad').val( getDiffTime() );
});
function fixTimeString(time){
var hours = Number(time.match(/^(\d+)/)[1]);
var minutes = Number(time.match(/:(\d+)/)[1]);
var AMPM = time.match(/\s(.*)$/)[1];
if(AMPM == "PM" && hours<12) hours = hours+12;
if(AMPM == "AM" && hours==12) hours = hours-12;
var sHours = hours.toString();
var sMinutes = minutes.toString();
if(hours<10) sHours = "0" + sHours;
if(minutes<10) sMinutes = "0" + sMinutes;
return sHours + ':' + sMinutes + ':00';
}
function getDiffTime(){
var start_time = fixTimeString($('#from_ad').val());
var end_time = fixTimeString($('#to_ad').val());
var start = new Date("1970-1-1 " + end_time).getTime(),
end = new Date("1970-1-1 " + start_time).getTime();
return parseInt(((start - end) / 1000 / 3600, 10)*100) / 100;
}
But the total_ad input is displaying only integer values.
How can I fix this problem?
Math.round rounds to the nearest integer, multiply and divide instead
var start = new Date("1970-1-1 " + start_time).getTime(),
end = new Date("1970-1-1 " + end_time).getTime();
var total = (parseInt(((start-end) / 1000 / 3600)*100, 10)) / 100;
FIDDLE
When you take the time 15:15:00 and subtract 13:00:00, you're left with 2.15 hours, not 3.15, and this example would return 2.15 even without making sure there is only two decimals, but for other times that might not be the case.
You could also use toFixed(2), but that would leave you with 3.00 and not 3 etc.
This is how I calculate it:
calculateDiff();
function calculateDiff(){
_start = "7:00 AM";
_end = "1:00 PM";
_start_time = parseAMDate(_start);
_end_time = parseAMDate(_end);
if (_end_time < _start_time){
_end_time = parseAMDate(_end,1);
}
var difference= _end_time - _start_time;
var hours = Math.floor(difference / 36e5),
minutes = Math.floor(difference % 36e5 / 60000);
if (parseInt(hours) >= 0 ){
if (minutes == 0){
minutes = "00";
}
alert(hours+":"+minutes);
}
}
function parseAMDate(input, next_day) {
var dateReg = /(\d{1,2}):(\d{2})\s*(AM|PM)/;
var hour, minute, result = dateReg.exec(input);
if (result) {
hour = +result[1];
minute = +result[2];
if (result[3] === 'PM' && hour !== 12) {
hour += 12;
}
}
if (!next_day) {
return new Date(1970, 01, 01, hour, minute).getTime();
}else{
return new Date(1970, 01, 02, hour, minute).getTime();
}
}

Bootstrap Datepicker defaults to 1900's when entered with 2 digit year

I am using a datepicker in a modal window in my Bootstrap application. I am using the original Datepicker from Stefan Petre. I built it where it works in a desktop and mobile using a mouse and it works fine.
Recently I had a user request to allow it to also work with a keyboard. I removed the readonly property to allow the user to enter a date in the input field. The date-format is set to 'mm/dd/yyyy'.
When I enter a date like today for example like this "12/11/13" then it will default to 1913. This isn't a huge deal as I could just train the users to use 4 digits, but I would rather just have it default to this century.
Note: This only seems to happen for the date-format with a 4 digit year. This also seems to happen in the same manner in the newer forks of Stefan's code.
Note: I am using Bootstrap 2.0.4. I am testing with Firefox.
Here is what it looks like:
In JavaScript, set the datepicker's assumeNearbyYear attribute to true, like this:
$("#dp").datepicker({
assumeNearbyYear: true
});
This happens because the Bootstrap datepicker is using JavaScript Date objects. When you create a new Date object and pass in a two digit year it will output 1900+year (see Why does Javascript evaluate a 2-digit year of 00 as 1900 instead of 2000?)
You could try to tweak the datepicker source code, but that might be too complicated.
From what I can see on http://www.eyecon.ro/bootstrap-datepicker/ there is no option to set a range for the selectable dates, but you could change the format to use two digit years.
On your screenshot I can see, that you are using the datepicker for "Arrival Date" which I assume is in the future. On the website there is an example on how to disable dates in the past.
I hope that helps.
UPDATE
I have written an event handler for your problem which should do the trick.
Javascript on http://jsfiddle.net/pCYbd/1/
$("#dp").datepicker();
$("#dp").on("keyup", function(e) {
var date, day, month, newYear, value, year;
value = e.target.value;
if (value.search(/(.*)\/(.*)\/(.*)/) !== -1) {
date = e.target.value.split("/");
month = date[0];
day = date[1];
year = date[2];
if (year === "") {
year = "0";
}
if (year.length < 4) {
newYear = String(2000 + parseInt(year));
$(this).datepicker("setValue", "" + month + "/" + day + "/" + newYear);
if (year === "0") {
year = "";
}
return $(this).val("" + month + "/" + day + "/" + year);
}
}
});
CoffeeScript on http://jsfiddle.net/pCYbd/2/
$("#dp").datepicker()
$("#dp").on "keyup", (e) ->
value = e.target.value
if value.search(/(.*)\/(.*)\/(.*)/) != -1
date = value.split("/")
month = date[0]
day = date[1]
year = date[2]
year = "0" if year == ""
if year.length < 4
newYear = String(2000 + parseInt(year))
$(#).datepicker("setValue", "#{month}/#{day}/#{newYear}")
year = "" if year == "0"
$(#).val("#{month}/#{day}/#{year}")
My JavaScript skills are not the best, but this should work.
Updating bootstrap-datepicker.js as shown in this post solved it for me https://github.com/eternicode/bootstrap-datepicker/pull/1461/commits/2ea16adad27cbc4d4dfa20b924addfb480e5b036
yyyy: function(d,v){
if (format.parts.indexOf('yyyy') > -1 && v < 1000) v = 2000+v; // this line ***
return d.setUTCFullYear(v);
},
I'm using bootstrap-datepicker v1.5.1 and if you look around line 1741 where it does the year mapping, you will notice this:
yyyy: function (d, v) {
return d.setUTCFullYear(v);
},
yy: function (d, v) {
return d.setUTCFullYear(2000 + v);
},
When you specify that the control uses a four year date "yyyy", it will only do the return d.setUTCFullYear(v);, which will get you the previous century that JavaScript gives you. When you specify that it use the two year date "yy", it will do the correct 2000+ that you need for the current century.
So if you want the correct two year date to be 2016, 2017, etc., you need to set your datepicker to use the "yy" like so:
$('#tbPurchaseDate').datepicker({
format: 'mm/dd/yy',
autoclose: true,
todayBtn: 'linked',
todayHighlight: true,
orientation: 'bottom auto'
});
Or you can change the "yyyy" setting in the bootstrap-datepicker.js to match the "yy" version, but then you'd have to remember to do that every time you update the datepicker js file via nuget. It's much easier to just change your format setting.
Of course, if you want the full 4 digit year to display in the control, then you might want to try one of the elaborate fixes listed here or just set the "yyyy" to what the "yy" is in the js file.
Or just update your code to the latest version (1.6.4 right now) and "yyyy" and "yy" are the same and you use assumeNearbyYear: true as noted in another answer here.
For me, the best solution was to customize parseDate function in bootstrap-datepicker.js file directly. Inside a function, there is variable setters_map with yyyy property which I modified a bit. Here is my solution:
yyyy: function(d,v) {
if (v.toString().length == 2 && v <= 30) {
v = 2000 + parseInt(v);
}
return d.setUTCFullYear(v);
},
In my case it was needed to convert only years that are less or equals 30.
In the update function of bootstrap-datepicker.js I added this block of code:
var str = this.element.prop('value');
var defaulted = false;
if (str.lastIndexOf("/") >= 0 && (str.match(/\//g) || []).length == 2)
{
var yr = str.substring(str.lastIndexOf("/") + 1);
if (yr.length <= 2)
defaulted = true;
}
if (this.date.getFullYear() < 2000 && defaulted) {
this.date.setFullYear(this.date.getFullYear() + 100);
}
right before the viewdate is set on this line:
this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);
It will work 100% if you update below two line in UTCDate() of bootstrap-datepicker.js core file:
function UTCDate(){
/* Date defaulted date from 2000 if entered date year less than 4 degit*/
if(arguments!=null && arguments[0].toString().length<4)
arguments[0] = 2000 + arguments[0];
return new Date(Date.UTC.apply(Date, arguments));
}

Working with Dates in Google Apps Script

What I am trying to do here is this - I want to give index to only the workdays in each week.
So, if in a week, Monday and Wednesday are holidays, then Tuesday should get 1, Thursday should get 2, Friday should get the index 3. Otherwise, in a normal week without any holidays, Monday should get 1, Tuesday 2, Wednesday 3, and so on ...
Here is the code I have written (I haven't coded in years now, so please pardon the crude approach)
Sheet 'Holidays' contains a list of holidays in the column B starting from row 2
Variable date is the date for which I want to find out the index for
Variable dayOfTheWeek is the number of day of 'date' counted from last Sunday, so if date is a Monday, dayOfTheWeek is 1; if date is Tuesday, dayOfTheWeek is 2, and so on ...
function indexOfWorkdayOfTheWeek (date, dayOfTheWeek, lastSundayDate)
{
var activeSheet = SpreadsheetApp.getActiveSpreadsheet();
var activeCell = activeSheet.getActiveRange();
var activeRow = activeCell.getRowIndex();
var activeColumn = activeCell.getColumn();
var count = 1;
for (var j = 1; j < dayOfTheWeek; j++)
{
var date2 = lastSundayDate.valueOf() + j*86400;
Logger.log('Date ' + j + ' is:' + date2);
Logger.log('Last Sunday is:' + lastSundayDate);
if (holidayOrNot(date2) == true)
{
}
else
{
count = count + 1;
}
}
return count;
}
function holidayOrNot(date2)
{
var holidaysSheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Holidays');
var listOfHolidays = holidaysSheet.getSheetValues(2, 2, 95, 1);
var isDateMatch = false;
for (var k = 0; k < 90; k++)
{
if (date2 == listOfHolidays[k].valueOf())
{
isDateMatch = true;
break;
}
else
{
continue;
}
}
return isDateMatch;
}
I think the problem is two-fold here:
The date2 calculation isn't working for some reason (var date2 = lastSundayDate.valueOf() + j*86400;)
The function holidayOrNot is returning false, no matter what, even if it encounters a holiday ... the condition date2 == listOfHolidays[k] isn't working for some reason...
Help would be appreciated!
maybe this method below could help you in your calculations, it returns an integer corresponding to the day of the year so if you apply this to your holidays days and compare to the days of interest it could be a good way to find matches.
here it is, just add these lines outside of any function in your script (so you can use it anywhere) then use it like this :
var d = new Date().getDOY();
Logger.log(d)
Here the method :
Date.prototype.getDOY = function() {
var onejan = new Date(this.getFullYear(),0,1);
return Math.ceil((this - onejan) / 86400000);
}
Assuming that lastSundayDate is being passed around correctly, I see a glaring problem:
lastSundayDate.valueOf().
valueOf() on Date objects returns the primitive value... it looks like you're going for adding a day to the date (86400 seconds * j)? I can't tell what the logic is supposed to be here. But the valueOf() date2 is definitely giving you an integer something like: 1384628769399 (see here).
What you really want to accomplish is something like Date.getDay(), or something similar so that you can add hours, days, etc. to the original Date. This is likely the source of all your problems.
What you can do is read the Mozilla Developer Network documentation on Date objects to see all of the functions on Dates and their uses. You can greatly simplify what you're trying to do by using these functions, instead of doing abstract operations like j * 86400.
It should also be noted that you can do simple operations such as the following, to add 4 hours to the current Date (time):
var myDate = new Date();
Logger.log(myDate); // ~ console.write
var laterDate = new Date(myDate.setHours(myDate.getHours() + 4));
Logger.log(laterDate); // ~ console.write
which gives the following:
[13-11-16 14:13:38:947 EST] Sat Nov 16 14:13:38 GMT-05:00 2013
[13-11-16 14:13:38:954 EST] Sat Nov 16 18:13:38 GMT-05:00 2013
Working with dates can be tricky - but it's always best to use the simplest methods that are available, which are built into the Date objects themselves. There are also numerous other libraries that provide extended functionality for Dates such as Date js.
If you're still running into your problem after attempting to try using methods I displayed above, please run your script and post both the Execution Transcript and the content of the Logger so that I can help you narrow down the issue :)

jQuery addition function giving me NaN

I am using the following function to add all of my line totals together. Each of the totals will be a decimal number such as 23.45 . When the user enters any qty into any of text input boxes it should fire the function, but all I'm getting at the moment in grandtotal is NaN, who's nan is it and why is she messing with my script?
By the way, each of the linetotals is a span, which is filled with the line total calculation once a quantity is entered into the qty text box.
So basically, user comes along, selects a price from the line one drop down, so lets say 20.00 , they then enter the quantity into the text box qty, let's say 2, jQuery then multiplies qty by priceeach and output into the span with the id linetotal1. What I want to do is add all of the linetotals together for a grand total, but lets say if they don't enter anything into line 2, linetotal2, 3, 4, 5 will them be empty.
<script>
$(document).ready(function () {
$('input').on('keyup', function () {
linetotal1 = $('#linetotal1').text(),
linetotal2 = $('#linetotal2').text(),
linetotal3 = $('#linetotal3').text(),
linetotal4 = $('#linetotal4').text(),
linetotal5 = $('#linetotal5').text(),
grandtotal = parseFloat(linetotal1) + parseFloat(linetotal2) + parseFloat(linetotal3) + parseFloat(linetotal4) + parseFloat(linetotal5);
$('#grandtotal').text(grandtotal);
}); });
</script>
You could just loop from 1-5, and have the value default to 0 if it's a blank string:
var rawValue, grandtotal = 0;
for(var i=1; i<6; i++)
{
rawValue = $.trim($('#linetotal' + i).text());
if(rawValue == '') rawValue = 0;
grandtotal += parseFloat(rawValue);
}
$('#grandtotal').text(grandtotal);
jsFiddle Demo
If you wanted to do something a bit fancier with jQuery you could select each of the spans based on the ID starting with linetotal. This would work if you added more spans, where as with the for loop, you'd have to update the count. It would be better if the spans all had a common class, which you could use to easily select them.
var rawValue, grandtotal = 0;
$('span[id^="linetotal"]').each(function(i, elem){
rawValue = $.trim($(this).text());
if(rawValue == '') rawValue = 0;
grandtotal += parseFloat(rawValue);
});
$('#grandtotal').text(grandtotal);
jsFiddle Demo
You should do this by loop, i have done this before for my client check if my code helps you
var disValue = new Array();
var this_size = document.getElementsByName("myVal").length;
sum = 0;
for (i=0; i<this_size; i++)
{
disValue[i] = document.getElementsByName("myVal")[i].value;
}
for (i=0; i<this_size; i++)
{
sum = parseFloat(sum)+ parseFloat(disValue[i]);
}
if (sum != 0) {
document.getElementById("disc_test").innerHTML="<?php echo $this->__('You are saving') ?> "+sum +" <?php echo $this->__('on this order') ?>!";
}
ignore php tags :)