Columns: Custom Date Formats

This idea came up while making another script which I'll post soon. It seemed like a general feature so I took it out into its own script. I didn't write the function that handles the formatting but took it from Jacob Wright.

Background: In Opus, the traditional approach to formatting dates has been to tweak the time and date settings at the Windows level under Region and Language.

You can also override your system-wide settings via Preferences / Miscellaneous / Advanced: [Information Display] custom_date_format and similar setttings.

But sometimes, it might be nice to have a date column in a custom format, in addition to your normal date column. This script lets you define date columns using the PHP date syntax, so you can have date columns like these:


The three custom columns above are defined with this simple syntax:

'YMD' : {
   target: "modify",
   format: "ymd"
},

'D.M.Y' : {
   target: "modify",
   format: "d.m.y"
},

'the date' : {
   target: "modify",
   format: "D j M, Y"
}

Something Special:

If you look inside the script, you'll see there is also a facility to easily define "special columns" that are handled separately from the standard "Format My Date" columns.


How To Install:

It was a bit rushed, so feedback welcome! :slight_smile:

Updating:

ScriptWizard-compatible.

Script Code:

The script code, from the download above, is reproduced here for reference.

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
/////                    FORMAT MY DATE                   /////
/////                 defines date columns                ///// 
/////         using php's date formatting syntax          /////
////                 http://php.net/manual/en/function.date.php
/////    powered by this date formatting function:        /////
////                http://jacwright.com/projects/javascript/date_format/ 
////  thanks to Leo & Jonathan for waking me up today!    /////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////



///////////////////////////////////////////////////////////////
//   TO DEFINE THE COLUMNS: SCROLL ONE PAGE DOWN             //
///////////////////////////////////////////////////////////////



// Opus calls OnInit to initialize the script add-in
function OnInit(initData) {
   var uid = "172DF1FA-AAA7-488F-A838-2105BC6E3489";
   var url = "http://resource.dopus.com/viewtopic.php?f=35&t=24668";
// basic information about the script
  initData.name = "Format My Date";
  initData.desc = "Adds date columns with a custom format";
  initData.copyright = "playful 2015";
// In addition, the formatting script is copyright Jacob Wright 2005  
  initData.min_version = "11.5.1"
  initData.version = "1.0.1";
  initData.default_enable = true;

  // The following prefix is added to the column names when looking at columns in 
  // the Folder Format panel, in order to distinguish the column from 
  // similar columns from other scripts. 
  // The prefix will not show in the actual column header
  var ColumnPrefix = "formatmydate_";


// Add all columns (create ScriptColumn objects via AddColumn()
// See http://www.gpsoft.com.au/help/opus11/index.html#!Documents/Scripting/ScriptColumn.htm
  for(var key in columns) {
      if (columns.hasOwnProperty(key)) {
       var column = columns[key];
       var cmd = initData.AddColumn();
       cmd.autorefresh = true;     
       cmd.defsort =  (typeof column.sort === 'undefined') || (column.sort != "DESC")  ? 1 : -1;     
       cmd.defwidth =  (typeof column.width === 'undefined') ? 5 : column.width;     
       cmd.header = key;
       cmd.infotiponly = (typeof column.infotiponly === 'undefined') ? false : column.infotiponly;
       cmd.justify = (typeof column.justify === 'undefined') ? "left" : column.justify;
       cmd.label = ColumnPrefix + key;
       cmd.method = "OnDateColumn";
       cmd.name = key;
       cmd.namerefresh = true;
       cmd.type = (typeof column.type === 'undefined') ? null : column.type;
   }
  }
} // End OnInit

///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////
/////       DEFINE YOUR DATES (i.e. COLUMNS) HERE        /////
///////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////

 // For the date columns, you set at least TWO properties: 
 // 1. "target", i.e. which date to use. Possible values are modify, modify_utc, create, create_utc, access, access_utc
 //    See http://www.gpsoft.com.au/help/opus11/index.html#!Documents/Scripting/Item.htm
 // 2. "format", e.g. "ymd" or "D M, Y". 
 //     For the format syntax, see http://php.net/manual/en/function.date.php
 // In addition, several properties are optional:
 // 3. "width" (optional) to set the columns default width in characters.
 // 4. "justify" (optional), i.e. should the column be justified "left", "right", "center" or "path". The default is "left".
 // 5. "sort" (optional). When set to "DESC", if you click on the column to sort it, it will first sort in descending order
 // 6. "type" (optional). The column defaults to plain text, but it can also be set to number, double, size, zip, percent, igraph, date, time, datetime, stars 
 // 7. "infotiponly" (optional): when set to true, the column will only dispay in file hover info tips, which are defined for file types in the file type editor
   


var columns = { 

'YMD' : {
   target: "modify",
   format: "ymd"
},

'D.M.Y' : {
   target: "modify",
   format: "d.m.y"
},

'the date' : {
   target: "modify",
   format: "D j M, Y"
},

'SomethingSpecial' : {
   // You can define a special column
   // without the usual properties
   // and handle it separately in the code
}



 };
///////////////////////////////////////////////////////////////
/////         END OF DATE / COLUMN DEFINITIONS            /////
///////////////////////////////////////////////////////////////



function OnDateColumn(ColumnData) {
  // OnDateColumn is an OnScriptColumn method
  // See http://www.gpsoft.com.au/help/opus11/index.html#!Documents/Scripting/OnScriptColumn.htm
  // ColumnData is a ScriptColumnData object
  // See http://www.gpsoft.com.au/help/opus11/index.html#!Documents/Scripting/ScriptColumnData.htm
  var colName = ColumnData.col;

  /////////////////////////////////////////////////
  ////    First, handle any special Columns    ////
  /////////////////////////////////////////////////

  // let's process a sample special column called SomethingSpecial   
  if (colName == 'SomethingSpecial') {
    ColumnData.value = "You're Special!";
  }


  /////////////////////////////////////////////////
  ////  Next, handle regular DATE  Columns     ////
  /////////////////////////////////////////////////

  else {

    // Do we have what we need?
    if( !columns[colName] || 
        (typeof columns[colName].target === 'undefined') 
        ||(typeof columns[colName].format === 'undefined')  
      ) {
      return;
      }

  var myDate = new Date(ColumnData.item[columns[colName].target]);
  ColumnData.value = myDate.formatMyDate(columns[colName].format);
  }
} // OnDateColumn


//////////////////////////////////////////////////////////
///////////////// formatMyDate /////////////////////////// 
// This is a function to format dates
// Source: http://jacwright.com/projects/javascript/date_format/
// Simulates PHP's date function
//////////////////////////////////////////////////////////
Date.prototype.formatMyDate = function(format) {
    var returnStr = '';
    var replace = Date.replaceChars;
    for (var i = 0; i < format.length; i++) {       var curChar = format.charAt(i);         if (i - 1 >= 0 && format.charAt(i - 1) == "\\") {
            returnStr += curChar;
        }
        else if (replace[curChar]) {
            returnStr += replace[curChar].call(this);
        } else if (curChar != "\\"){
            returnStr += curChar;
        }
    }
    return returnStr;
};

Date.replaceChars = {
    shortMonths: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
    longMonths: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
    shortDays: ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'],
    longDays: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],

    // Day
    d: function() { return (this.getDate() < 10 ? '0' : '') + this.getDate(); },
    D: function() { return Date.replaceChars.shortDays[this.getDay()]; },
    j: function() { return this.getDate(); },
    l: function() { return Date.replaceChars.longDays[this.getDay()]; },
    N: function() { return this.getDay() + 1; },
    S: function() { return (this.getDate() % 10 == 1 && this.getDate() != 11 ? 'st' : (this.getDate() % 10 == 2 && this.getDate() != 12 ? 'nd' : (this.getDate() % 10 == 3 && this.getDate() != 13 ? 'rd' : 'th'))); },
    w: function() { return this.getDay(); },
    z: function() { var d = new Date(this.getFullYear(),0,1); return Math.ceil((this - d) / 86400000); }, // Fixed now
    // Week
    W: function() { var d = new Date(this.getFullYear(), 0, 1); return Math.ceil((((this - d) / 86400000) + d.getDay() + 1) / 7); }, // Fixed now
    // Month
    F: function() { return Date.replaceChars.longMonths[this.getMonth()]; },
    m: function() { return (this.getMonth() < 9 ? '0' : '') + (this.getMonth() + 1); },
    M: function() { return Date.replaceChars.shortMonths[this.getMonth()]; },
    n: function() { return this.getMonth() + 1; },
    t: function() { var d = new Date(); return new Date(d.getFullYear(), d.getMonth(), 0).getDate() }, // Fixed now, gets #days of date
    // Year
    L: function() { var year = this.getFullYear(); return (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)); },   // Fixed now
    o: function() { var d  = new Date(this.valueOf());  d.setDate(d.getDate() - ((this.getDay() + 6) % 7) + 3); return d.getFullYear();}, //Fixed now
    Y: function() { return this.getFullYear(); },
    y: function() { return ('' + this.getFullYear()).substr(2); },
    // Time
    a: function() { return this.getHours() < 12 ? 'am' : 'pm'; },
    A: function() { return this.getHours() < 12 ? 'AM' : 'PM'; },
    B: function() { return Math.floor((((this.getUTCHours() + 1) % 24) + this.getUTCMinutes() / 60 + this.getUTCSeconds() / 3600) * 1000 / 24); }, // Fixed now
    g: function() { return this.getHours() % 12 || 12; },
    G: function() { return this.getHours(); },
    h: function() { return ((this.getHours() % 12 || 12) < 10 ? '0' : '') + (this.getHours() % 12 || 12); },
    H: function() { return (this.getHours() < 10 ? '0' : '') + this.getHours(); },
    i: function() { return (this.getMinutes() < 10 ? '0' : '') + this.getMinutes(); },
    s: function() { return (this.getSeconds() < 10 ? '0' : '') + this.getSeconds(); },
    u: function() { var m = this.getMilliseconds(); return (m < 10 ? '00' : (m < 100 ?
'0' : '')) + m; },
    // Timezone
    e: function() { return "Not Yet Supported"; },
    I: function() {
        var DST = null;
            for (var i = 0; i < 12; ++i) {
                    var d = new Date(this.getFullYear(), i, 1);
                    var offset = d.getTimezoneOffset();

                    if (DST === null) DST = offset;
                    else if (offset < DST) { DST = offset; break; }                     else if (offset > DST) break;
            }
            return (this.getTimezoneOffset() == DST) | 0;
        },
    O: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + '00'; },
    P: function() { return (-this.getTimezoneOffset() < 0 ? '-' : '+') + (Math.abs(this.getTimezoneOffset() / 60) < 10 ? '0' : '') + (Math.abs(this.getTimezoneOffset() / 60)) + ':00'; }, // Fixed now
    T: function() { var m = this.getMonth(); this.setMonth(0); var result = this.toTimeString().replace(/^.+ \(?([^\)]+)\)?$/, '$1'); this.setMonth(m); return result;},
    Z: function() { return -this.getTimezoneOffset() * 60; },
    // Full Date/Time
    c: function() { return this.format("Y-m-d\\TH:i:sP"); }, // Fixed now
    r: function() { return this.toString(); },
    U: function() { return this.getTime() / 1000; }
};
 
///////////////////////////////////////////////////////////////////////////////
function OnAboutScript(data){ //v0.1
	var cmd = DOpus.Create.Command();
	if (!cmd.Commandlist('s').exists("ScriptWizard")){
		if (DOpus.Dlg.Request("The 'ScriptWizard' add-in has not been found.\n\n"+
"Install 'ScriptWizard' from [resource.dopus.com].\nThe add-in enables this dialog and also offers "+
"easy updating of scripts and many more.","Yes, take me there!|Cancel", "No About.. ", data.window))
		cmd.RunCommand('http://resource.dopus.com/viewtopic.php?f=35&t=23179');}
	else
		cmd.RunCommand('ScriptWizard ABOUT WIN='+data.window+' FILE="'+Script.File+'"');
}

//MD5 = "1e35bc1577b955c3c5d93c0fbe3ad7c0"; DATE = "2015.06.19 - 14:13:36"
1 Like

Thanks for sharing your custom date column! o) Could you change the subject of your thread to match something like?
Column: FormatMyDate (custom date strings)
The prefix "Add-In:" is surely correct, but does not help to determine what kind of add-in. That prefix also hasn't been used before, so it does create unnessary noise in the list of available things. Just a recommendation, I'm not a moderator. o)

Hi tbone, thank you for explaining the thread naming convention, that's done.
Also I was wondering if you could please let me know if there's anything missing for compatibility with your ScriptWizard.
I re-upped using the "Prepare for Upload" feature, hope it's alright.
Thanks!

You're welcome and thanks as well! o) Regarding the SW support, you did quite correct so far - script-id and script-url are set just right and the about-feature is working perfectly, I tried! o)

The only thing to do is: Place your attachment "inline" and fill the file-comment located in the "Attachments" section (on the right hand side) with version/date information. I recommend something like "v / - ". This could look similar to this for your recent upload "v1.01 / 2015.06.19 - intial version (SW support added)". Currently, the version-string you put "somewhere", cannot be connected to your attachment, as it is just text with no reference to the script-upload. This results in SW not finding any version information, auto-updating does not work currently.

The best thing to make sure everything works as desired is trying to update your own local script. Even though no update will happen (because your local file is identical/newer or has been modified), SW will talk to you if it has problems finding required version information in this thread.

Hi tbone, thank you, your system is working perfectly, great to learn about it, I'll use that for the next one (and just converted jon's GoExisting).
I changed the version to 1.0.1 (I don't think anyone else had downloaded 1.01 so it won't matter.)
Thanks Bruder!