在Windows下使用任何语言环境的工作日

Ric*_*ton 9 windows locale r character-encoding

我想要获得一周中的某一天,并让它在任何地方都能保持一致.在使用拉丁字母的语言环境中,一切都很好.

Sys.getlocale()
## [1] "LC_COLLATE=English_United Kingdom.1252;LC_CTYPE=English_United Kingdom.1252;LC_MONETARY=English_United Kingdom.1252;LC_NUMERIC=C;LC_TIME=English_United Kingdom.1252"
weekdays(Sys.Date())
## [1] "Tuesday"
Run Code Online (Sandbox Code Playgroud)

我和其他语言环境有两个相关的问题.

如果我订

Sys.setlocale("LC_ALL", "Arabic_Qatar")
## [1] "LC_COLLATE=Arabic_Qatar.1256;LC_CTYPE=Arabic_Qatar.1256;LC_MONETARY=Arabic_Qatar.1256;LC_NUMERIC=C;LC_TIME=Arabic_Qatar.1256"
Run Code Online (Sandbox Code Playgroud)

然后我有时(正确地)得到

weekdays(Sys.Date())
## [1] "????????
Run Code Online (Sandbox Code Playgroud)

有时会得到

weekdays(Sys.Date())
## [1] "ÇáËáÇËÇÁ"
Run Code Online (Sandbox Code Playgroud)

取决于我的设置.问题是,我无法弄清楚造成这种差异的原因.

我认为这可能与某些事情有关getOption("encoding"),但我已经尝试过明确设置options(encoding = "native.enc")并且options(encoding = "UTF-8")没有任何区别.

我已经尝试了几个最新版本的R,并且所有这些问题都是一致的.

目前,字符串在R GUI中正确显示,但在使用IDE(Architect和RStudio测试)时不正确.

我应该设置什么以确保工作日始终正确显示?

知道它weekdays(Sys.Date())等同于format(as.POSIXlt(Sys.Date()), "%A")调用内部format.POSIXlt方法可能会有所帮助.

其次,改变所有语言环境似乎有点过头了.我以为我应该能够设置时间选项.但是,如果我设置了区域设置的各个组件,则weekdays返回一串问号.

for(category in c("LC_TIME", "LC_CTYPE", "LC_COLLATE", "LC_MONETARY"))
{
  Sys.setlocale(category, "Arabic_Qatar")
  print(Sys.getlocale())
  print(weekdays(Sys.Date()))
}
## [1] "LC_COLLATE=English_United Kingdom.1252;LC_CTYPE=English_United Kingdom.1252;LC_MONETARY=English_United Kingdom.1252;LC_NUMERIC=C;LC_TIME=Arabic_Qatar.1256"
## [1] "????????"
## [1] "LC_COLLATE=English_United Kingdom.1252;LC_CTYPE=Arabic_Qatar.1256;LC_MONETARY=English_United Kingdom.1252;LC_NUMERIC=C;LC_TIME=Arabic_Qatar.1256"
## [1] "????????"
## [1] "LC_COLLATE=Arabic_Qatar.1256;LC_CTYPE=Arabic_Qatar.1256;LC_MONETARY=English_United Kingdom.1252;LC_NUMERIC=C;LC_TIME=Arabic_Qatar.1256"
## [1] "????????"
## [1] "LC_COLLATE=Arabic_Qatar.1256;LC_CTYPE=Arabic_Qatar.1256;LC_MONETARY=Arabic_Qatar.1256;LC_NUMERIC=C;LC_TIME=Arabic_Qatar.1256"
## [1] "????????"
Run Code Online (Sandbox Code Playgroud)

区域设置的哪些部分会影响工作日的打印方式?


更新:问题似乎与Windows相关.当我在具有区域设置的Linux机器上运行代码时"ar_QA.UTF8",工作日会正确显示.


进一步更新:正如他在答案中提到的agstudy,在Windows下设置区域设置是奇怪的,因为你不能只使用像"en-GB"这样的ISO代码.对于Windows 7/Vista/Server 2003/XP,您可以使用setlocale语言字符串或本地语言支持值设置语言环境.对于Qatari Arabic,没有setlocale语言字符串,因此我们必须使用NLS值.我们有几个选择:

Sys.setlocale("LC_TIME", "ARQ")    # the language abbreviation name
Sys.setlocale("LC_TIME", "Arabic_Qatar") # corresponding to the language/country pair "Arabic (Qatar)"
Sys.setlocale("LC_TIME", "Arabic_Qatar.1256") # explicitly including the ANSI codepage
Sys.setlocale("LC_TIME", "Arabic") # would sometimes be a possibility too, but it defaults to Saudi Arabic
Run Code Online (Sandbox Code Playgroud)

所以问题不在于R不能支持Windows下的阿拉伯语语言环境(尽管我并不完全相信它的健壮性Sys.setlocale).


绝望的最后一次尝试:尝试通过使用Windows Management Instrumentation命令来神奇地修复操作系统区域设置无法正常工作,因为R似乎无法识别更改.

system("wmic os set locale=MS_4001") 
## Updating property(s) of '\\PC402729\ROOT\CIMV2:Win32_OperatingSystem=@'
## Property(s) update successful.
system("wmic os get locale") # same as before
Run Code Online (Sandbox Code Playgroud)

ags*_*udy 5

命名语言环境的系统是特定于操作系统的.我建议您阅读R安装和管理手册中的语言环境以获得完整说明.

在Windows下:

MSDN语言字符串列出了受支持的语言列表.令人惊讶的是,那里没有阿拉伯语."语言字符串"列包含用于在R中设置区域设置的合法输入,甚至在列表contry/regions字符串中也没有国家/地区使用阿拉伯语.

当然,您可以更改区域设置全局设置(面板设置 - >区域 - > ..),但这将全局更改它,并且不确定在没有编码问题的情况下获得正确的输出.

在linux下(在我的情况下是ubuntu):

默认情况下,通常不支持阿拉伯语,但很容易使用阿拉伯语locale.

 locale -a                     ## to list all already supported language
 sudo locale-gen ar_QA.UTF-8   ## install it in case does not exist
Run Code Online (Sandbox Code Playgroud)

现在在RStudio下:

 Sys.setlocale('LC_TIME','ar_QA.UTF-8')
[1] "ar_QA.UTF-8"

> format(Sys.Date(),'%A')
[1] "????????
Run Code Online (Sandbox Code Playgroud)

另请注意,在R控制台下,打印不像R studio那样漂亮,因为它是从左到右而不是从右到左书写.


Ric*_*ton 5

RStudio/Architect问题

通过明确地将工作日字符串的编码更改为UTF-8,可以稍微解决这个问题.

current_codepage <- as.character(l10n_info()$codepage)
iconv(weekdays(Sys.Date()), from = current_codepage, to = "utf8")
Run Code Online (Sandbox Code Playgroud)

请注意,代码页仅存在于Windows上; l10n_info()$codepageNULL在Linux上.

LC_TIME问题

事实证明,在Windows下,你必须同时设置LC_CTYPELC_TIME语言环境类别,并且你必须设置LC_CTYPE之前LC_TIME,否则将无法正常工作.


最后,我们需要针对不同操作系统的不同实现.

Windows版本:

get_today_windows <- function(locale = NULL)
{
  if(!is.null(locale))
  {
    lc_ctype <- Sys.getlocale("LC_CTYPE")
    lc_time <- Sys.getlocale("LC_TIME")
    on.exit(Sys.setlocale("LC_CTYPE", lc_ctype))
    on.exit(Sys.setlocale("LC_TIME", lc_time), add = TRUE)
    Sys.setlocale("LC_CTYPE", locale)
    Sys.setlocale("LC_TIME", locale)
  }
  today <- weekdays(Sys.Date())
  current_codepage <- as.character(l10n_info()$codepage)
  iconv(today, from = current_codepage, to = "utf8")
}
get_today_windows() 
## [1] "Tuesday"
get_today_windows("French_France")
## [1] "mardi"
get_today_windows("Arabic_Qatar")
## [1] "????????"
get_today_windows("Serbian (Cyrillic)") 
## [1] "??????"
get_today_windows("Chinese (Traditional)_Taiwan") 
## [1] "???"
Run Code Online (Sandbox Code Playgroud)

Linux版本:

get_today_linux <- function(locale = NULL)
{
  if(!is.null(locale))
  {
    lc_time <- Sys.getlocale("LC_TIME")
    on.exit(Sys.setlocale("LC_TIME", lc_time), add = TRUE)
    Sys.setlocale("LC_TIME", locale)
  }
  weekdays(Sys.Date())
}
get_today_linux() 
## [1] "Tuesday"
get_today_linux("fr_FR.utf8")
## [1] "mardi"
get_today_linux("ar_QA.utf8")
## [1] "????????"
get_today_linux("sr_RS.utf8") 
## [1] "??????"
get_today_linux("zh_TW.utf8") 
## [1] "??"
Run Code Online (Sandbox Code Playgroud)

.utf8在区域设置中强制执行编码似乎很重要get_today_linux("zh_TW"),但显示不正确.