I am not completely sure, but as far as I understand it, Tengwar not only uses a number system with base of 12, but it also places the least significant digit to the left.
The following code creates a user macro \tengwarnumeral that converts a number to its Tengwar counterpart. It does so by first converting the number to a sequence that represents the single digits of the Tengwar number (where the order of digits is already flipped) and then replacing the strings in this sequence by the correct glyph using the tengwarscript package.
\documentclass{article}
\pdfmapfile{=tengwarscript.map}
\usepackage[annatar]{tengwarscript}
\ExplSyntaxOn
\int_new:N \l_tengwarnumeral_tempa_int
\int_new:N \l_tengwarnumeral_tempb_int
\seq_new:N \l_tengwarnumeral_tengwardigits_seq
\NewDocumentCommand { \tengwarnumeral } { m } {
\seq_clear:N \l_tengwarnumeral_tengwardigits_seq
\int_set:Nn \l_tengwarnumeral_tempa_int { #1 }
\int_do_until:nn { \l_tengwarnumeral_tempa_int <= 0 } {
\int_set:Nn \l_tengwarnumeral_tempb_int { \int_mod:nn { \l_tengwarnumeral_tempa_int } { 12 } }
\int_compare:nNnTF \l_tengwarnumeral_tempb_int = { 0 } {
\int_sub:Nn \l_tengwarnumeral_tempa_int { 12 }
} {
\int_sub:Nn \l_tengwarnumeral_tempa_int { \l_tengwarnumeral_tempb_int }
}
\int_set:Nn \l_tengwarnumeral_tempa_int { \int_div_truncate:nn \l_tengwarnumeral_tempa_int { 12 } }
\seq_put_right:Nx \l_tengwarnumeral_tengwardigits_seq { \int_use:N \l_tengwarnumeral_tempb_int }
}
\seq_map_inline:Nn \l_tengwarnumeral_tengwardigits_seq {
\str_case:nn { ##1 } {
{ 0 } { \Tzero }
{ 1 } { \Tone }
{ 2 } { \Ttwo }
{ 3 } { \Tthree }
{ 4 } { \Tfour }
{ 5 } { \Tfive }
{ 6 } { \Tsix }
{ 7 } { \Tseven }
{ 8 } { \Teight }
{ 9 } { \Tnine }
{ 10 } { \Tten }
{ 11 } { \Televen }
}
}
}
\ExplSyntaxOff
\begin{document}
\tengwarnumeral{3}
% is 12 + 3, so should be: 3 1
\tengwarnumeral{15}
% is 1728 + 144 + 120 + 3, so should be: 3 10 1 1
\tengwarnumeral{1995}
\end{document}

If you want to use Unicode-flavoured fonts with fontspec, such as Tengwar Telcontar, you can adjust the second part of the macro where the conversion takes place as follows (I also added the Unicode codepoints that the Tengwar numerals would be assigned to if the latest encoding proposal would be accepted):
\documentclass{article}
\usepackage{fontspec}
\newfontfamily\tengwarfont{tengtelc.ttf}
\ExplSyntaxOn
\int_new:N \l_tengwarnumeral_tempa_int
\int_new:N \l_tengwarnumeral_tempb_int
\seq_new:N \l_tengwarnumeral_tengwardigits_seq
\NewDocumentCommand { \tengwarnumeral } { m } {
\seq_clear:N \l_tengwarnumeral_tengwardigits_seq
\int_set:Nn \l_tengwarnumeral_tempa_int { #1 }
\int_do_until:nn { \l_tengwarnumeral_tempa_int <= 0 } {
\int_set:Nn \l_tengwarnumeral_tempb_int { \int_mod:nn { \l_tengwarnumeral_tempa_int } { 12 } }
\int_compare:nNnTF \l_tengwarnumeral_tempb_int = { 0 } {
\int_sub:Nn \l_tengwarnumeral_tempa_int { 12 }
} {
\int_sub:Nn \l_tengwarnumeral_tempa_int { \l_tengwarnumeral_tempb_int }
}
\int_set:Nn \l_tengwarnumeral_tempa_int { \int_div_truncate:nn \l_tengwarnumeral_tempa_int { 12 } }
\seq_put_right:Nx \l_tengwarnumeral_tengwardigits_seq { \int_use:N \l_tengwarnumeral_tempb_int }
}
\group_begin:
\tengwarfont
\seq_map_inline:Nn \l_tengwarnumeral_tengwardigits_seq {
\str_case:nn { ##1 } {
{ 0 } { \char"E070 } % \char"160B0
{ 1 } { \char"E071 } % \char"160B3
{ 2 } { \char"E072 } % \char"160E2
{ 3 } { \char"E073 } % \char"160E3
{ 4 } { \char"E074 } % \char"160E4
{ 5 } { \char"E075 } % \char"160E5
{ 6 } { \char"E076 } % \char"160E6
{ 7 } { \char"E077 } % \char"160E7
{ 8 } { \char"E078 } % \char"160E8
{ 9 } { \char"E079 } % \char"160E9
{ 10 } { \char"E07A } % \char"160EA
{ 11 } { \char"E07B } % \char"160EB
}
}
\group_end:
}
\ExplSyntaxOff
\begin{document}
\tengwarnumeral{3}
% is 12 + 3, so should be: 3 1
\tengwarnumeral{15}
% is 1728 + 144 + 120 + 3, so should be: 3 10 1 1
\tengwarnumeral{1995}
\end{document}