Compute Sunrise and Sunset Taking Into Account Daylight Savings in PHP

A requirement came up to plot some graphs with surface sun indicated, and it is useful to show the sun rise and sun set.

The following code snippet shows how to do this when providing a latitude, longitude and day name (Monday through Sunday).

    $gDay = "Friday";
    $gLat = "51.1";
    $gLongs = "0.5"; // "-99.99" would be west of the Greenwich Meridian

    // GMT or BST?
    if (date('I', time())) {
    	$iOffset = 1; // Daylight saving set == BST
    	$sSavings = "BST";
    } else {
    	$iOffset = 0; // GMT
    	$sSavings = "GMT";
    // compute sunset and rise using $gDay ... as this changes the further out in days you go
    if (($iTime = strtotime("next ".$gDay)) === false) {
	$sSunset = date_sunset(time(), SUNFUNCS_RET_STRING, $gLat,$gLongs, 90, $iOffset);
	$sSunrise = date_sunrise(time(), SUNFUNCS_RET_STRING, $gLat,$gLongs, 90, $iOffset);
    } else {
	$sSunset = date_sunset($iTime, SUNFUNCS_RET_STRING, $gLat,$gLongs, 90, $iOffset);
	$sSunrise = date_sunrise($iTime, SUNFUNCS_RET_STRING, $gLat,$gLongs, 90, $iOffset);
    $sTailName .= "\nSunrise: $sSunrise -> Sunset: $sSunset ($sSavings)";

The variable $sTailName contains the result as a printable string.

Soundings Replot Utility for RASP

Having been asked to add some RASP sounding plots in Northern Ireland, it became apparent that a script to just test just the ones added would make life easier (than replotting sounding by hour from the command line).Then it became an idea to just have this to replot all soundings (as potentially to do them later on a differnet host).

The script below is the result, fixed for one model with fixed start end points. These can of course be extended/changed as approriate.

# Script expects a model as the first parameter,
# e.g. " EI12"
# Also expects "replot" to be available in $HOMEDIR/GM and it works

# Set where the RASP setup lives

# Set where are commands are ... useful to put full path if run
# from a cron job. Ensure they exist, or add a check for it.

# Check we got a model and date to plot
if [ $# -eq 2 ]
echo "Using input as '$1'"
echo "Using '$REPLOT_CMD' to replot"
echo "Using date as '$2'"
echo "Provide a model to try. E.g. UK12 2015-04-03"

case $1 in
EI12) # We'll do just the one here
# Set the start and end sounding number (as in soundingXX)
SEQ1=$(SEQ_CMD -s " " $val1 $val2)
# Set the start end of hours to use
SEQ2=$(SEQ_CMD -f "%02g" -s " " $val3 $val4)
# Set the model to use and clear out the temp folder where
# we will put the results
echo "Don't know this model to work out start and finish: $1"

# Now sort out the results folder ...
# Clear it out
rm -rf $TMP_FOLDER

# Output what we set
START_SND=$(printf '%d' "$val3")
END_SND=$(printf '%d' "$val4")
START_HR=$(printf '%02d' "$val1")
END_HR=$(printf '%02d' "$val2")

echo "Sounding sequence: sounding$SEQ1"
echo "Hour sequence: $SEQ2"
echo "Sending results to: $TMP_FOLDER"
echo "Using date of: $2"

#Now do plots, assuming no gaps though
for SND_NAME in $SEQ1
for PROC_HR in $SEQ2
echo "$REPLOT_CMD -r $MODEL -d $TMP_FOLDER -p $SOUNDING_NAME -l $TMP_FOLDER -w $MODEL_FOLDER/wrfout_d02_$2_$PROC_HR\:00\:00"
$HOMEDIR/GM/replot -r $MODEL -d $TMP_FOLDER -p $SOUNDING_NAME -l $TMP_FOLDER -w $MODEL_FOLDER/wrfout_d02_$2_$PROC_HR\:00\:00


Difference Bearing Calculator in PHP

A long standing application checks the actual weather reports for various UK airfileds and then compares to a forecast. One of the variables is the wind direction.

The application compares a compass bearing for the actual and forecasted wind direction and then states the difference in degrees. All sounds easy. Alas the first release of PHP code for this seemed to be incorrect for the fourth quarter (i.e. Q4 is between 270 and 360 degrees).

Here’s the code that has now been proven to work.

Function FindBearing( $forecast, $actual )

    if ($actual == "VRB") { 
        // the forecast has variable so we return zero 
        // as it could be anything given the winds are light, 
        // that's not something we can handle
        return 0;
    if  ($forecast <= 180 ) { // in Q1 or Q2
        if ( $actual <= 180 ) { // in Q1 or Q2
            return abs($actual - $forecast);
        // forecast in Q3 or Q4
        return 180-abs((360-$actual)-abs(180-$forecast));
    } else { // forecast in Q3 or Q4
        if ( $actual > 180 ) { // forecast in Q3 and Q4 as well so easy
            return abs($actual - $forecast);
        // forecast in Q3 or Q4 and forecast in Q1 and Q2
        $result = abs($actual - $forecast);
        if ($result <= 180){
            return $result;
        return 180 - abs(180-$result);

    // else return a bearing that isn't possible     
    return "-1";

The function can be tested by using this simple PHP script:

for ($i = 0; $i <= 360; $i=$i + 1) {
        for ($j = 0; $j <= 360; $j=$j + 1) {
            $diff = FindBearing( $i, $j );
            echo "
forecast=$i, actual=$j, diff=$diff"; if (($diff < 0) || ($diff>180)){ echo "ERROR"; } } }

Unix Shell CGI Script using find, stat or xarg for File Listing

This little code snippet was required to find out the date and time for files for use in a CGI script.

It uses a conventional shell script to start with, setting some local variables to use in the script. It then outputs the HTML content type to enable CGI working.

After that it it uses find with the output as a printf statement. The nice thing about using printf is that we can just select the name of the file without the full path (you don’t want to tell the world exactly where it lives!).

 NOW=$(date +"%H:%M:%S %d-%h-%Y")
 echo "Content-type: text/html"
 echo ""
 echo ""
 echo "
 echo "

Production Times and Sizes at $NOW

" echo "
 find $RUNPATH -name "$PATTERN*" -printf "%AD %Ar %10s %f\n"
 echo "

And that’s it!

You can change the format specifiers in the printf to suit what you want.

A sample output looks like this:

Production Times and Sizes at 13:31:07 04-Jul-2013

07/04/13 08:04:31 AM      77956 00fcst-movie-FULL-UK2.flv
07/04/13 06:20:23 AM      61540 00fcst-movie-FULL-UK2.wmv
07/04/13 06:20:22 AM     124996 00fcst-movie-FULL-UK2.avi
07/04/13 11:30:06 AM    8061942 00fcst-movie-FULL-UKEA62-WINDOW.wmv
07/04/13 11:30:05 AM    6447314 00fcst-movie-FULL-UKEA62-WINDOW.avi
07/04/13 11:30:06 AM    4371525 00fcst-movie-FULL-UKEA62-WINDOW.flv
07/04/13 11:41:05 AM    4409202 00fcst-movie-FULL-UK4.flv
07/04/13 07:05:02 AM    8527096 00fcst-movie-FULL-UK4.wmv
07/04/13 07:05:02 AM   11068020 00fcst-movie-FULL-UK4.avi

You can of course consider using stat and xarg, by replacing the tail of the find like this if you do want the full path:

find $RUNPATH | grep $PATTERN | xargs stat -c "%y %10s %n"

Unix Shell Script Checking BST/GMT

A problem over the last weekend when the clocks went forward, showed there was a need to do resolve to how the GMT cron jobs should work on a few servers working together (when timing is important).

For a couple of years I simply changed the hour in the crontab on each server and left it at that, but alas this is open to error across multiple severs, so I decided to do something about it.

The first step was to put the cron table into GMT hours (i.e. ensure all jobs would run as GMT as normal). The next step was to introduce for the “morning run” of work, a check to sleep for an hour if the server is in British Summer Time (BST). We can find this out by using:


Which can give an output like this:

Mon Apr  1 12:17:55 BST 2013

All we want is the local time zone daylight savings flag and then do something if that is BST. We can get just this flag if we use the %Z parameter to the date command.

Here’s a little bit of code to wait if we’ve run in GMT but need to wait an hour due to BST:

# --- GMT checking - we assume run in GMT timeframe
GMTBST=`date '+%Z'`
if [ $GMTBST == BST ]
        # must be in summertime, so wait an hour
        echo "Found the date has $GMTBST. Sleeping for $SLEEPPERIOD seconds ..."
        sleep $SLEEPPERIOD
        echo "Not BST, carrying on"

This is then done for the afternoon run and the same again for the evening run.

Note this may cause a problem if multiple scripts check this as they may get serial delays. This works best if you have one main job, and the check is done once.

So now the script will check if it is GMT or BST and wait an hour if BST.