I’ve been meaning to get my thoughts down for quire some time.
Mrs. ParrTech and I went to Vegas last year for our 30th anniversary. After having visited Vegas many times previously, I was completely disappointed, and here’s why.
I’ve been meaning to get my thoughts down for quire some time.
Mrs. ParrTech and I went to Vegas last year for our 30th anniversary. After having visited Vegas many times previously, I was completely disappointed, and here’s why.
I looked up how to count the number of Sundays between two dates…. the so-called answer shocked me. There are a couple of popular answers, but they are horribly inefficient.
Let me show you a better way…..
Update 4/22/2025
Due to a severe copy and paste error, the formulas were completely wrong. 8-(
These have now been corrected.
Let’s say we have the following cells:
A | B | |
1 | Start | 1/1/2025 |
2 | End | 5/1/2025 |
3 | Which Day | 1 |
We will follow the Excel convention, where Sunday = 1, to find the number of “1” days (cell B3) between 1/1/2025 (cell B1) and 5/1/2025 (cell B2).
Between the two dates:
=INT((B2-(B1+B3-WEEKDAY(B1)+7))/7)+1
Correctly returns 17
Between and including the two dates:
=INT((B2-(B1+B3-WEEKDAY(B1)+7))/7)+1+IF(WEEKDAY(B1)=B3,1,0)
Correctly returns 17. If we were to change B1 to 1/5 (a Sunday), the result would be 16 without the extra IF term.
For a more detailed explanation…
Google Chrome (and possibly, other browsers) don’t properly honor the Cache-Control header.
If you are on Page A, click a link for Page B, then hit the back button to go back to Page A, Chrome uses a pre-rendered, cached version of Page A, which may now have stale content.
Action | Location |
---|---|
Start | Page A 8:05 AM |
Click link on Page A | Page B 8:10 AM |
Hit browser back button | Page A 8:05 AM |
At this point, Page A is basically static. Any dynamic content won’t be refreshed, even if it executes in Javascript.
Disrupting this behavior is known as “cache busting”.
Add this Javascript to your page’s <HEAD> section:
<SCRIPT> function nocache(){ var tc3=new Date(); var delta=tc3-tc1; if (delta>2000) { window.location.reload(); } else { tc1=tc3; } } var tc1=new Date(); setInterval(nocache,1000); </SCRIPT>
When the page first executes, it creates a Javascript variable tc1 with a current timestamp.
Then, it sets up a timer callback function, nocache(), which executes every 1 second.
When nocache executes, it creates a new timestamp (tc3), and if the difference between the two is greater than 2 seconds, it reloads the current page. If not, it updates the tc1 timestamp to current.
The result is that if the page remains static for more than 2 seconds, it will refresh. However, as long as the page is active, it keeps updating the timestamp in tc1 instead.
If you click the link to Page B, wait 2 or more seconds, then hit the browser’s back button, the timestamp in tc1 will be the point in time from when the link was clicked (more than 2 seconds ago). One second after you hit the back button, the nocache function sees that tc1 is more than 2 seconds out of date and reloads the page. If the page successfully reloads, tc1 is updated in the process. If not, it simply retries the reload every 1 second.
Also, if your page uses JSON or XML to dynamically render content, the nocache timer function can simply call your page’s update function rather than reload the entire page.
When you hit the browser’s back button, Chrome tries very hard to use a pre-rendered page from cache rather than use the Cache-Control header or contact the server to see if the page is stale (which it should be doing). This means that when you hit the back button, any dynamic code has already executed, and the page picks up where it left off from a script execution standpoint. Unfortunately, this includes any events that have fired, which means that the pre-rendered version of the page is basically static.
I have seen other solutions that use the onpageshow event, or other event hooks. However, I have found these to be unreliable in Chrome for cache busting. In contrast, the timer hook must be honored for basic page functionality, and therefore can’t simply be killed off like other events.
A side effect of this approach is that if the server is unavailable and the page tries to refresh, it will get stuck in a refresh loop until the server is available again. This is not necessarily a negative behavior, but could easily be fine tuned using a counter, for example, to only try to refresh a set number of times and then stop. During page load, “retries” is set to some number, n. “Retries > 0” is then added as a condition to the if block, which then decrements retries during each execution. If retries hits zero, it updates tc1 to current, which stops all attempts. In another variation, retries can be its own, outer “if” block, so that some other exit action can be executed, for example, alerting the user that the server is offline and the page is stale.
A fleshed-out version would look like this:
<SCRIPT> function nocache() { var tc3=new Date(); var delta=tc3-tc1; if (retries>0) { // Normal action if (delta>2000) { retries-=1; window.location.reload(); } else { tc1=tc3; } } else { // When retries hits zero, set error text, make the element visible, and disable the nocache timer var e=document.getElementById("ErrorText"); e.innerHTML="The server is offline and this page is dead. Have a nice day."; e.style.visibility="visible"; clearInterval(nocachetimer); } } var tc1=new Date(); var retries=3; var nocachetimer=setInterval(nocache,1000); </SCRIPT> <DIV ID=ErrorText STYLE='visibility:hidden; display:block;'> </DIV>
I hope you find this useful, and thanks for reading!
Update, 5/14/2023: Version 3.2
Update, 5/11/2023: Version 3.1. Original: Version 2
I wrote a javascript calculator while I was waiting for something the other day. Here it is:
Permalink: Here
Technical Details
To Do
(Updated, 5/11/2023)
Funny Story about 3.1 vs 3.2
I uploaded version 3.1, and patted myself on the back for having done such a great job. Right-click, save as HTML, fire it up in Chrome, and…everything was rendering twice.
What happened??
The UI is dynamic, but the saved version of the page had BOTH a static copy of the dynamically-generated HTML, as well as the javascript code to dynamically generate the HTML. So every UI element was rendered TWICE. Worse, if you modify the Javascript at the top of the file to alter the constants or the display size, you would have one copy that’s correct because it’s dynamic, but the static copy would still be wrong.
Interestingly, if you View Source and save from there, it won’t have that problem, but that’s not what I was after.
To fix this, I changed from document.write to using extra SPANs for each block of UI elements, and setting innerHTML. Despite the fact that saving the file includes a static copy of the HTML, the dynamic code simply overwrites it each time the page is loaded. So if you change a Javascript variable and reload, the dynamic code blows away the static HTML and replaces it with a correct version.
Do you like it? Feel free to copy it. Click the permalink. Then right-click the calculator, and select “Save as html”.
Ideas or suggestions? Please feel free to leave me a comment.
After 7 months of continuous issues, I think I finally beat the problems with the front gate, but the way I did it might surprise you.
Two bad lines of code took this entire site down. Here is what you can learn from my mistake.
Why did the quantum chicken cross the road?
Why did the quantum cat cross the road?
As a follow-up to Monitor and TV Buying Guide – 2022, I built a simple calculator to tell you the approximate width and height of the screen, given its diagonal measurement and aspect ratio.
Permalink: Screen Size Calculator
In 2015, I wrote this post: Justin’s Rules for Buying a House.
These were things that I had learned when I was shopping for a house in 2002, and solidified in to a tangible list when a couple of friends of mine were house shopping in 2015.
After shopping for a house in 2019 and moving out to the country, here are a few more things I’ve added to my list.
If you travel in 2023, travelling with tech is unavoidable. After reading a completely unhelpful, but similarly-titled ZD article that read more like an Apple fanboy post, I decided to write something that’s actually helpful.