Currently using React to build an App, using one of Nasa's API's. The API returns one Json value, for that specific day. I would ideally like to show the previous days, "picture of the day" on the app as well. The API url is
https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2020-07-23
Trying to figure out how I can dynamically change the date within the URL, to show the previous 4 days. I know a function would be best served here but can't wrap my head around how to potentially do it.
Like this?
Using URLSearchParams and Date.toISOString
const changeDate = (urlString, days) => {
let url = new URL(urlString);
let date = new Date(url.searchParams.get("date") + "T15:00:00.000Z"); // or new Date(); date.setHours(15,0,0,0) // normalise at 3pm
date.setDate(date.getDate() + days);
url.searchParams.set("date", date.toISOString().split("T")[0]);
return url.href;
};
let newUrl = changeDate("https://api.nasa.gov/planetary/apod?api_key=DEMO_KEY&date=2020-07-23", -4)
console.log(newUrl)
Here is my problem.
I'm developing an webapp, written in Angular and NOT jQuery, for a client that need to have its database refreshed every week with new sets of data. So they chose to use SQLite3 because they can drop the new DB into a folder and the sales rep can download this DB file every Monday. But there are a series of data that gets cached on localStorage and those data need to be refreshed as soon as the iPad checks the DB file and returns true if is a new file. So, I'm using XMLHttpRequest() to check the head for the "Last-Modified" date and it works perfect on Chrome and Safari, but once I build the app and move to iPad, the Last-Modified date return null. I searched everywhere in the web to try find what could be wrong, but I just could not find any satisfactory answer:
The code I'm using is
var dbPath = "db/myDb.sqlite";
var getMTime = function(url, callback) {
var xhr = new XMLHttpRequest();
xhr.open('HEAD', dbPath, true);
xhr.onreadystatechange = function() {
if (xhr.readyState === 4 && xhr.status === 200) {
var mtime = new Date(xhr.getResponseHeader('Last-Modified'));
if (mtime.toString() === 'Invalid Date') {
callback(); // dont want to return a bad date
} else {
callback(mtime);
}
}
}
xhr.send();
};
Thanks in advance for the help
UPDATE
Looks like the IOS WebView wipes the HEAD object response... So, thats why by running xhr.getResponseHeader I get empty object, but I would love to know if there is an alternative for that and why this object is being wiped...
Is there a way I can get the load time of a URL or page from Jquery? For example, I make ajax request to "http://www.yahoo.com", I want to know how long it took to load the page completely. I am aware of the same domain policy. But I just want to write a simple javascript utility that can let me know page load time.
I know there are tools like YSlow etc, but I want this utility to be running continuously in browser tab and alert(javascript) alert when the page load time is beyond some threshold.
Thanks,
J
Something like this should work nicely.
var startTime;
$.ajax({
// url, type, dataType, etc
beforeSend: function(xhr){
startTime = +new Date();
}
complete: function(xhr, state){
var latency = (+new Date()) - startTime;
window.console.log(latency);
}
});
I you are using $.ajax you can set a variable with the start time in a function called by the "beforeSend" option like:
var start = (new Date()).getTime();
Then set another variable with the "complete" option like:
var finish= (new Date()).getTime();
Then compare the two to get the number of seconds like:
var secs = (finish-start)/1000;
Or once you set the start variable, use "setInterval()" to check the start variable against the current time until it exceeds a threshold.
But you know there is the "timeout" option in $.ajax too, which is covered pretty well here and may be helpful:
Determine if $.ajax error is a timeout
My question is Client time only displayed, But want to display server time every seconds.
function GetCount(ddate,iid){
var date = new Date();
dateNow = date;
// if time is already past
if(amount < 0){
}
// else date is still good
else{
days=0;hours=0;mins=0;secs=0;out="";
amount = Math.floor(amount/1000);//kill the "milliseconds" so just secs
days=Math.floor(amount/86400);//days
amount=amount%86400;
hours=Math.floor(amount/3600);//hours
amount=amount%3600;
mins=Math.floor(amount/60);//minutes
amount=amount%60;
secs=Math.floor(amount);//seconds
document.getElementById(iid).innerHTML=days;
document.getElementById('countbox1').innerHTML=hours;
document.getElementById('countbox2').innerHTML=mins;
document.getElementById('countbox3').innerHTML=secs;
setTimeout(function(){GetCount(ddate,iid)}, 1000);
}
}
If you want to avoid all that network traffic checking the time with the server every second just: (1) have the server pass the time in a way that you store in a JS variable on page load; (2) also store the client time as at page load; (3) use setInterval to update the time (every 1000 milliseconds or as often as you want) by getting current client time minus client time at page load as an offset of server time at page load. (Obviously this will all go wrong if the user updates their PC clock while your page is running, but how many users would do that? And would it be the end of the world if they did?)
If you really want the actual server time every second - why? Seems a bit of a waste of bandwidth for little if any benefit, but if you must do it use Ajax as already suggested. If you're not familiar with Ajax I'd suggest using Google to find some tutorials - if you use JQuery you can do it with only a couple of lines of code. Easy.
Or put your onscreen clock in an IFRAME that repeatedly reloads itself. Just because I sometimes miss the days of IFRAMEs.
If you run into the issue that the server time is different from the client-side clock, I lookup a server time delta in minutes just once, and then I add it to the minutes of a new Date():
var refDateTime = new Date();
refDateTime.setMinutes(refDateTime.getMinutes() + getServerTimeDelta());
// ...
var serverTimeDelta;
function getServerTimeDelta(recalc) {
var xmlHttp;
if (recalc || !serverTimeDelta) {
try {
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest();
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
}
} catch(err1) {
//IE
try {
xmlHttp = new ActiveXObject('Msxml2.XMLHTTP');
} catch(err2) { /* swallow it */ }
}
if (xmlHttp) {
xmlHttp.open('HEAD', window.location.href.toString(), false);
xmlHttp.setRequestHeader("Content-Type", "text/html");
xmlHttp.send('');
var serverDateTime = xmlHttp.getResponseHeader("Date");
if (serverDateTime) {
var dateNow = new Date();
var serverDate = new Date(serverDateTime);
var delta = serverDate.getTime() - dateNow.getTime();
// Convert to minutes
serverTimeDelta = parseInt((delta / 60000) + '');
if (!serverTimeDelta) serverTimeDelta = 0.01;
} else {
serverTimeDelta = 0.011; // avoid auto recalc
}
} else {
serverTimeDelta = 0.012;
}
}
return serverTimeDelta;
}
You need your server to supply the time to JavaScript, either on page load or via XMLHttpRequest.
To get the server time from the client side in javascript you will need to make an ajax call.
Do you know how to make that type of call?
You will basically make another page (or web method etc) which displays/returns the time. You will then use a XMLHttpRequest object to make the call and get the result.
How can i get the current time? (in JavaScript)
Not the time of your computer like:
now = new Date;
now_string = addZero(now.getHours()) + ":" + addZero(now.getMinutes()) + ":" + addZero(now.getSeconds());
But the real accurate world time?
Do i need to connect to to a server (most likely yes, which one? and how can i retrieve time from it?)
All the searches I do from google return the (new Date).getHours().
Edit:
I want to avoid showing an incorrect time if the user has a wrong time in his computer.
You can use JSON[P] and access a time API:
(The code below should work perfectly, just tested it...)
function getTime(zone, success) {
var url = 'http://json-time.appspot.com/time.json?tz=' + zone,
ud = 'json' + (+new Date());
window[ud]= function(o){
success && success(new Date(o.datetime));
};
document.getElementsByTagName('head')[0].appendChild((function(){
var s = document.createElement('script');
s.type = 'text/javascript';
s.src = url + '&callback=' + ud;
return s;
})());
}
getTime('GMT', function(time){
// This is where you do whatever you want with the time:
alert(time);
});
First, to get the accurate GMT time you need a source that you trust. This means some server somewhere. Javascript can generally only make HTTP calls, and only to the server hosting the page in question (same origin policy). Thus that server has to be your source for GMT time.
I would configure your webserver to use NTP to synchronize its clock with GMT, and have the webserver tell the script what time it is, by writing a variable to the page. Or else make and XmlHttpRequest back to the server when you need to know the time. The downside is that this will be inaccurate due to the latency involved: the server determines the time, writes it to the response, the response travels over the network, and the javascript executes whenever the client's cpu gives it a timeslice, etc. On a slow link you can expect seconds of delay if the page is big. You might be able to save some time by determining how far off from GMT the user's clock is, and just adjusting all the time calculations by that offset. Of course if the user's clock is slow or fast (not just late or early) or if the user changes the time on their PC then your offset is blown.
Also keep in mind that the client can change the data so don't trust any timestamps they send you.
Edit:
JimmyP's answer is very simple and easy to use: use Javascript to add a <script> element which calls a url such as http://json-time.appspot.com/time.json?tz=GMT. This is easier than doing this yourself because the json-time.appspot.com server works as a source of GMT time, and provides this data in a way that lets you work around the same-origin policy. I would recommend that for simple sites. However it has one major drawback: the json-time.appspot.com site can execute arbitrary code on your user's pages. This means that if the operators of that site want to profile your users, or hijack their data, they can do that trivially. Even if you trust the operators you need to also trust that they have not been hacked or compromised. For a business site or any site with high reliability concerns I'd recommend hosting the time solution yourself.
Edit 2:
JimmyP's answer has a comment which suggests that the json-time app has some limitations in terms of the number of requests it can support. This means if you need reliability you should host the time server yourself. However, it should be easy enough to add a page on your server which responds with the same format of data. Basically your server takes a query such as
http://json-time.appspot.com/time.json?tz=America/Chicago&callback=foo
and returns a string such as
foo({
"tz": "America\/Chicago",
"hour": 15,
"datetime": "Thu, 09 Apr 2009 15:07:01 -0500",
"second": 1,
"error": false,
"minute": 7
})
Note the foo() which wraps the JSON object; this corresponds to the callback=foo in the query. This means when the script is loaded into the page it will call your foo function, which can do whatever it wants with the time. Server-side programming for this example is a separate question.
Why don't you send the time with every page? For example somewhere in the html:
<span id="time" style="display:none;">
2009-03-03T23:32:12
</span>
Then you could run a Javascript while the site loads and interpret the date. This would reduce the amount of work the network has to do. You can store the corresponding local time and calculate the offset every time you need it.
You could use getTimezoneOffset to get the offset between the local date and the GMT one, and then do the math. But this will only be as accurate as the user's clock.
If you want an accurate time, you should connect to a NTP server. Because of the Same Origin Policy, you can't make a request with JS to another server then yours. I'd suggest you to create a server-side script that connects to the NTP server (in PHP, or whatever language you want) and return the accurate date. Then, use an AJAX request to read this time.
A little addition to Mr. Shiny and New and James answers
Here is a PHP script which you can place on own server and use instead of json-time.appspot.com
<?php
header('Content-Type: application/json');
header("Expires: Tue, 01 Jan 1990 00:00:00 GMT");
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
$error = "false";
$tz = $_GET['tz'];
if ( !in_array($tz, DateTimeZone::listIdentifiers())) {
$error = 'invalid time zone';
$tz = 'UTC';
}
date_default_timezone_set($tz);
?>
<?php echo htmlspecialchars($_GET['callback'], ENT_QUOTES, 'UTF-8' ); ?>({
"tz": "<?php echo $tz ?>",
"hour": <?php echo date('G'); ?>,
"datetime": "<?php echo date(DATE_RFC2822); ?>",
"second": <?php echo intval(date('s')); ?>,
"error": "<?php echo $error; ?>",
"minute": <?php echo intval(date('i')); ?>
})
Like Mr. Shiny and New said, you need a server somewhere with correct time. It can be the server where you site are or some other server that sends the correct time in a format that you can read.
If you want to use the date several times on your page, one or more seconds apart, you probably don't want to get the time from the server every time, but instead cache the difference and use the clients clock. If that is the case, here is one of many solutions:
var MyDate = new function() {
this.offset = 0;
this.calibrate = function (UTC_msec) {
//Ignore if not a finite number
if (!isFinite(UTC_msec)) return;
// Calculate the difference between client and provided time
this.offset = UTC_msec - new Date().valueOf();
//If the difference is less than 60 sec, use the clients clock as is.
if (Math.abs(this.offset) < 60000) this.offset = 0;
}
this.now = function () {
var time = new Date();
time.setTime(this.offset + time.getTime());
return time;
}
}();
Include it on your page and let your server side script produce a row like:
MyDate.calibrate(1233189138181);
where the number is the current time in milliseconds since 1 Jan 1970. You can also use your favorite framework for AJAX and have it call the function above. Or you can use the solution JimmyP suggested. I have rewritten JimmyPs solution to be included in my solution. Just copy and paste the following inside the function above:
this.calibrate_json = function (data) {
if (typeof data === "object") {
this.calibrate (new Date(data.datetime).valueOf() );
} else {
var script = document.createElement("script");
script.type="text/javascript";
script.src=(data||"http://json-time.appspot.com/time.json?tz=UTC") +
"&callback=MyDate.calibrate_json";
document.getElementsByTagName('head')[0].appendChild(script);
}
}
this.calibrate_json(); //request calibration with json
Notice that if you change the name of the function from MyDate you have to update the callback in this.calibrate_json on the line script.src.
Explanation:
Mydate.offset is the current offset between the server time and the clients clock in milliseconds.
Mydate.calibrate( x ); is a function that sets a new offset. It expects the input to be the current time in milliseconds since 1 Jan 1970. If the difference between the server and client clock is less than 60 seconds, the clients clock will be used.
Mydate.now() is a function that returns a date object that has the current calibrated time.
Mydate.calibrate_json( data ) is a function that either takes an url to a resource that gives back a datetime reply, or an object with the current time (used as a callback). If nothing is supplied, it will use a default url to get the time. The url must have a question mark "?" in it.
Simple example of how to update an element with the current time every second:
setInterval(
function () {
var element = document.getElementById("time");
if (!element) return;
function lz(v) {
return v < 10 ? "0" + v : v;
}
var time = MyDate.now();
element.innerHTML = time.getFullYear() + "-" +
lz(time.getMonth() + 1) + "-" +
lz(time.getDate()) + " " +
lz(time.getHours()) + ":" +
lz(time.getMinutes()) + ":" +
lz(time.getSeconds())
;
},1000);
I stumbled upon another solution for those who do not have access to the server side of things. An answer to the question Getting the default server time in jQuery?.
Basically, you can grab the "Date" header by doing an AJAX HEAD request to "/". Not all servers support this and it may take some jiggery-pockery to get it working with a particular server.
Check out the real answer for more details.
IMO, simplest solution is spinning up an AWS Lambda (or Google Serverless) and attaching it via API Gateway, giving you a timeserver without managing any infrastructure. My Lambda code:
import datetime
import json
def lambda_handler(event, context):
dt = datetime.datetime.utcnow()
return {
'statusCode': 200,
'body': json.dumps({
'iso_time': dt.strftime('%Y-%m-%dT%H:%M:%SZ')
})
}
We've used an API from EarthTools with much success:
EarthTools
The service returns XML with information such as the current GMT & timezone offsets (when supplying a latitude & longitude). We used a WebClient in conjunction with an XMLDocument in the VB backend of our ASP.NET page to read & interpret the XML.
Since the service related to the James's answer seems no longer working, I found another good rest API which can be used for this purpose, and it works fine.
The source is this site: timeapi and the code that you can use is simply this (using jQuery library and jsonp callback provided by the API):
$.getJSON("http://www.timeapi.org/utc/now.json?callback=?",function(json){
//console.log(json)
alert(json.dateString);
});
With this you will have the date and hour in the fomat like
September 02, 2016 09:59:42 GMT+0100
If you want to manipulate it in javascript, to have the hours, just transform it in a Date object like this:
new Date(json.dateString)
So, for example, you can write like this:
$.getJSON("http://www.timeapi.org/utc/now.json?callback=?",function(json){
var now = new Date(json.dateString);
var hours = now.toLocaleTimeString();
alert(hours)
});
in this way you will have the exact local time in hours.
Your can do this in PHP
<?php
$json = file_get_contents( "http://json-time.appspot.com/time.json?tz=GMT" );
$obj = json_decode($json);
$timenow= $obj->{'datetime'};
$hournow= $obj->{'hour'};
$minutenow= $obj->{'minute'};
$secondnow= $obj->{'second'};
?>
$timenow contains your full date & time: "Mon, 05 Mar 2012 01:57:51 +0000", $hournow: "1"
$minutenow: "57".
If your javascript is served from web server then you can use this simple function to request time from this server. It will work if server returns Date header in HTTP response.
function getServerTime()
{
var req = new XMLHttpRequest();
req.open('GET', document.location, false);
req.send(null);
return new Date(req.getResponseHeader("Date"));
}
Bacause of caching this may return wrong time. To fix this you can use random URL:
req.open('GET', "/time?r=" + Math.floor(Math.random()*10000000), false);