How to enforce a specific timezone ignoring system time

71 Views Asked by At

I am trying to convert an ISO date to EST, so that the user always sees EST, regardless of the system.

Like so

luxon.DateTime("2023-04-16T03:00:00Z").setZone("EST").toFormat('ttt')

Yet it always comes out like so:

10:00:00 PM GMT-5

I want:

10:00:00 PM EST

What am I doing wrong? I know EST is IANA compliant.

2

There are 2 best solutions below

2
hcharles25 On

To get the output in the format you desire (e.g., "10:00:00 PM EST"), you can use the setLocale method in combination with toFormat.

var result = luxon.DateTime.fromISO("2023-04-16T03:00:00Z")
  .setZone("America/New_York")
  .setLocale('en-US')
  .toFormat('hh:mm:ss a z');

console.log(result);
0
snickersnack On

This isn't trivial, for a couple reasons. First "EST" is not an IANA zone. Second, it doesn't totally make sense: "EST" roughly means "US Eastern time and also it is not currently DST", which of course is dependent on the latter actually being true. You are asking for it to say "EST" even when it is not actually EST.

The other answer pointed out that you could just use "Etc/GMT+5" (you can also just use { zone: -5 * 60 }) which will give you the right time, but then it won't format out "EST" when you print out the date, since it's not actually in the zone where "EST" is valid (there other other places besides the US on UTC-5).

That leaves us with writing a custom zone.

const DateTime = luxon.DateTime;

class AlwaysEST extends luxon.Zone {
  get type() {
    return "always est";
  }
  
  get name() {
    return "EST"
  }
  
  get isUniversal() {
    return true;
  }
  
  offsetName(_, opts) {
    return opts.format == "long" ? "Eastern Standard Time" : "EST";
  }
  
  formatOffset(_, format) {
    switch(format) {
      case "narrow": return "-5";
      case "short": return "-05:00";
      case "techie": return "-0500";
      default: "-05:00";
    }
  }
  
  offset(_) {
    return -5 * 60
  }
  
  equals(other) {
    return other && other.type == "always est";
  }
  
  get isValid() {
    return true;
  }

}

const customZone = new AlwaysEST();

console.log(DateTime.fromISO("2023-08-06T10:00:00-04:00", { zone: customZone }).toFormat("ttt"));
console.log(DateTime.fromISO("2023-08-06T10:00:00-04:00", { zone: customZone }).toFormat("tttt"));
console.log(DateTime.fromISO("2023-01-06T10:00:00-05:00", { zone: customZone }).toFormat("ttt"));
<script src="https://cdn.jsdelivr.net/npm/[email protected]/build/global/luxon.min.js"></script>