I would not recommend regexp for that. If you have one place with such a date, you can use transient/calculated property pair:

Class User.JSON Extends (%RegisteredObject, %JSON.Adaptor)
{

Property tsjson As %String(%JSONFIELDNAME = "ts") [ Transient ];

Property ts As %TimeStamp(%JSONINCLUDE = "none") [ SqlComputeCode = {set {*}=$replace({tsjson}," ", "T")_"Z"}, SqlComputed ];

/// d ##class(User.JSON).Test()
ClassMethod Test()
{
	set json = {"ts":"2022-02-02 01:01:34"}
	set obj = ..%New()
	zw obj.%JSONImport(json)
	w "ts:" _ obj.ts
}

}

If you have a lot of json properties,  use a custom datatype to do automatic conversion:

Class User.JSONTS Extends %Library.TimeStamp
{

ClassMethod IsValidDT(%val As %RawString) As %Status
{
    /// replace it with a real check
    q $$$OK
}

/// Converts the Objectscript value to the JSON number value.
ClassMethod JSONToLogical(%val As %Decimal) As %String [ CodeMode = generator, ServerOnly = 1 ]
{
    /// $replace({tsjson}," ", "T")_"Z"
    If 1,($$$getClassType(%class)=$$$cCLASSCLASSTYPEDATATYPE) || $$$comMemberKeyGet(%class,$$$cCLASSparameter,"%JSONENABLED",$$$cPARAMdefault) {
        Set %codemode=$$$cMETHCODEMODEEXPRESSION
        Set %code="$replace(%val,"" "", ""T"")_""Z"""
    } Else {
        Set %code=0 
    }
    Quit $$$OK
}

}

And use it instead of the standard timestamp:

Class User.JSON Extends (%RegisteredObject, %JSON.Adaptor)
{

Property ts As User.JSONTS;

/// d ##class(User.JSON).Test()
ClassMethod Test()
{
	set json = {"ts":"2022-02-02 01:01:34"}
	set obj = ..%New()
	zw obj.%JSONImport(json)
	w "ts:" _ obj.ts
}

}

You can do it like this:

1. Get active production:

w ##class(EnsPortal.Utils).GetCurrentProductionName()

2. Get a list of all BSes in an active production:

SELECT i.Name
FROM Ens_Config.Item i
JOIN %Dictionary.ClassDefinition_SubclassOf('Ens.BusinessService') c ON c.Name = i.ClassName
WHERE Production = ?

3. Disable all BSes (info)

for stop = 1, 0 {
  for i=1:1:$ll(bhList) {
    set host = $lg(bhList, i)
    set sc = ##class(Ens.Director).TempStopConfigItem(host, stop, 0)
  }
  set sc = ##class(Ens.Director).UpdateProduction()
}

4. Wait for all queues to empty:

SELECT TOP 1 1 AS "Processing"
FROM Ens.Queue_Enumerate()
WHERE "Count">0

5. Check that there are no active async BPs (extent size of all BPs must be 0 - here's an example)

6. Stop the production.

w ##class(Ens.Director).StopProduction()

After that and assuming deferred sending is not used (docs) it would be guaranteed that there are no in-flight messages.

Globals are cached in global buffer and you can use that.

  1. Create a new database CACHED with a distinct block size (16, 32, or 64 Kb).
  2. In your global buffer settings, set the global buffer for that block size to be equal to the amount of memory you want to allocate to the cache.
  3. Map cache global into a CACHED database.

This will give you an in-memory LRU cache. If you also follow @Dmitry.Maslennikov's suggestion and use PPG, nothing would be persisted. Otherwise you'll need to invalidate the persisted cache manually/by a task.

Here's the code I use (by @Dmitry Zasypkin):

/// Canonicalize XML.
/// in: XML string or stream to canonicalize.
/// out: Canonicalized XML is returned in this argument. If it's a string, out must be passed by refrence.
/// elementId: attrubute Id to canonicalize. If elementId="", the entire document would be canonicalized.
/// prefixList: a local of namespace=prefix pairs to add to a root tag, only in a case of exclusive canonicalization.
ClassMethod canonicalize(in As %Stream.Object, ByRef out As %Stream.Object, isInclusive As %Boolean = {$$$NO}, keepWhitespace = {$$$YES}, elementId As %String = "", ByRef prefixList As %String = "", writer As %XML.Writer = {##class(%XML.Writer).%New()}) As %Status
{
	#dim sc As %Status = $$$OK
	
	#dim importHandler As %XML.Document = ##class(%XML.Document).%New()
	set importHandler.KeepWhitespace = keepWhitespace
	
	if $isObject(in)
	{
		set sc = ##class(%XML.SAX.Parser).ParseStream(in, importHandler,, $$$SAXFULLDEFAULT-$$$SAXVALIDATIONSCHEMA)
	}
	else
	{
		set sc = ##class(%XML.SAX.Parser).ParseString(in, importHandler,, $$$SAXFULLDEFAULT-$$$SAXVALIDATIONSCHEMA)
	}
	if $$$ISERR(sc) quit sc
	
	if $isObject(in) && $isObject($get(out)) && (in = out) do in.Clear()
	
	if $isObject($get(out))
	{
		set sc = writer.OutputToStream(out)
	}
	else
	{
		set sc = writer.OutputToString()
	}
	if $$$ISERR(sc) quit sc
	
	#dim node As %XML.Node = importHandler.GetDocumentElement()
	if (elementId '= "") set node = importHandler.GetNode(importHandler.GetNodeById(elementId))

	// Main part
	if isInclusive
	{
		set sc = writer.Canonicalize(node, "c14n")
	}
	else
	{
		if (+$data(prefixList) >= 10)
		{
			#dim prefix As %String = ""
			for 
			{
				set prefix = $order(prefixList(prefix))
				if (prefix = "") quit
				do writer.AddNamespace(prefixList(prefix), prefix)
			}	
		}

		set sc = writer.Canonicalize(node)
	}
	if $$$ISERR(sc) quit sc
	
	if '$isObject($get(out))
	{
		set out = writer.GetXMLString(.sc)
		if $$$ISERR(sc) quit sc
	}
	
	do writer.Reset()
	
	quit $$$OK
}

If you have a web application /csp/SomeApp and users need to login to access this application, it is enough to go to a /csp/SomeApp web application configuration page and set Serve Files to Use InterSystems Security to get the effect you want. After making this change, users would not be able to access /csp/SomeApp/image.png without logging into your application first.

How do I set up the application folder and it's sub-folders to be inaccessible to casual browsing, and only allow the application to access them?

Depending on your goal, there are different approaches available. Do you want user to see images only after logging into the application (so a general control on resources) or do you want individual access (only some users can see a specified image)?

If it's a first one, go to the web application configuration page and set Serve Files to Use InterSystems Security. In that case if the user has permissions to view a csp/cls page in this application then allow them to view a static file, if they do not have permissions to view a csp/cls page then return a 404 page not found page.

For a second case, use REST Broker to serve files and implement arbitrary checks in the broker.

That depends on the precision you need.

1. If you need just close enough you can do this:

  • Check how much time, on avarage BS takes to run. Let's say X seconds
  • Set Call Interval on your BS to 86400-X
  • Start BS at 10:00 AM
  • Assuming average runtime stays constant it should work well enough

2. If you need to run your BS at exactly at 10:00 AM use this task to achieve that.